Outils pour utilisateurs

Outils du site


snippet:vala

Vala

Vala est un langage de programmation compilé, qui réutilise la « plateforme » GObject du projet GNOME.

Résoudre les redirections (302) avec libsoup

Dans l'exemple ci-dessous, nous allons utilisé le signal got-headers pour savoir si une ressource est directement accessible ou une redirection (302) est mise en place.

redirect.vala
/*
 * valac --pkg=glib-2.0 --pkg=libsoup-2.4 redirect.vala
 *
 * Find the real URL (it even works with 302 HTTP status code).
 */
 
using GLib;
using Soup;
 
 
public class Request : Object {
 
	private string url;
 
	public Request (string resource) {
		this.url = resource;
	}
 
	private string get_real_uri (string resource) {
		Session session;
		Message msg;
		string new_url = null;
 
		/* Create Soup.* objects */
		session = new Session ();
		msg = new Message ("GET", resource);
 
		/* Signal */
		msg.got_headers.connect (() => {
				/* 302 */
				if (msg.status_code == Status.FOUND) {
					new_url = msg.response_headers.get_one ("Location");
					/* Finish processing request */
					session.cancel_message (msg, Status.CANCELLED);
				}
		});
 
		session.send_message (msg);
 
		if (new_url == null) {
			new_url = "%s".printf (resource);
		}
 
		return new_url;
	}
 
	public void send () {
		/* Find the real URI */
		stdout.printf ("%s\n", get_real_uri (this.url));
	}
 
	public static int main (string[] args) {
		//string uri = "http://ftp.netbsd.org/pub/NetBSD/security/advisories/NetBSD-SA2016-005.txt.asc";
 
		//string uri = "http://rf.proxycast.org/1175697431602405376/13940-16.06.2016-ITEMA_21011329-0.mp3";
		string uri = "http://www.podtrac.com/pts/redirect.mp4/201406.jb-dl.cdn.scaleengine.net/bsdnow/2016/bsd-0146.mp4";
 
		var r = new Request (uri);
		r.send ();
 
		return 0;
	}
}

Les expressions régulières

Dans cet exemple, nous allons voir comment récupérer un morceau d'une chaîne de caractères, en nommant le pattern comme on peut le faire sous Python.

Je vous conseille de parcourir cette page (Cf. Named subpatterns).

regex.vala
/**
 * valac --pkg=glib-2.0 regex.vala
 *
 **/
 
 
public static int
main (string[] argv) {
 
	GLib.Regex re;
	GLib.MatchInfo info;
	string data = "!system=DEVFS subsystem=CDEV type=CREATE cdev=video90";
	// Python's way :)
	string pattern = "subsystem=CDEV type=CREATE cdev=(?P<device>video[0-9]+)";
 
	try {
		re = new GLib.Regex (pattern);
		if (re.match (data, 0, out info)) {
			stdout.printf ("%s\n", info.fetch_named ("device"));
		}
	} catch (GLib.RegexError e) {
		stderr.printf ("Error: %s\n", e.message);
	}
 
	return 0;
}
valac --pkg=glib-2.0 regex.vala
./regex
video90

Afficher le nombre de cœur du processeur

Ce bout de code fonctionne uniquement sous FreeBSD.

cpu.vala
/**
 * Compile with:
 * valac --pkg=glib-2.0 cpu.vala
 *
 * Get number of core processor.
 **/
 
private static string nb_cpu (string data) {
	string[] tokens;
	string cores = null;
 
	tokens = data.split (": ");
	if (tokens.length == 2) {
		cores = tokens[1];
	}
 
	return cores;
}
 
 
public static int main (string[] argv) {
	string cmd = "/sbin/sysctl hw.ncpu";
	string cores;
	string std_err = null;
	int status;
 
	try {
		GLib.Process.spawn_command_line_sync (cmd, out cores, out std_err,
											  out status);
 
		if (status == 0) {
			stdout.printf ("%s", nb_cpu (cores));
		}
	} catch (GLib.SpawnError e) {
		stderr.printf ("Error: %s\n", e.message);
	}
 
	return 0;
}

Fichier / dossier

Déterminer le MIME type d'un fichier

On doit charger les modules glib-2.0 et gio-2.0.

/*
 * Exemple d'utilisation pour deviner le type de fichier.
 *
 * valac --pkg glib-2.0 --pkg gio-2.0 content-type.vala
 */
 
class ContentType : Object {
 
	public static int main (string[] argv) {
		if (argv.length == 2) {
			GLib.File file = File.new_for_commandline_arg (argv[1]);
			try {
				GLib.FileInfo file_info = file.query_info (
					FileAttribute.STANDARD_CONTENT_TYPE,
					FileQueryInfoFlags.NONE,
					null);
 
				string content_type = file_info.get_content_type ();
 
				if (content_type == "image/png") {
					stdout.printf ("Ok\n");
				}
				else {
					stderr.printf ("No\n");
				}
			} catch (Error e) {
				stderr.printf ("%s", e.message);
			}
		}
		else {
			stderr.printf ("%s FILE\n", argv[0]);
		}
 
		return 0;
	}
}

On obtient pour une image PNG le résultat suivant :

./content-type ristretto.png
Ok

Or si l'on « porte » cette portion de code en C, le test ne va pas fonctionner, il faut utiliser la fonction g_content_type_is_a.

Depuis Vala >= 0.12 GLib.g_content_is_a est obsolète, on doit plutôt utiliser GLib.ContentType.is_a.

On remplace ce test dans l'exemple ci-dessus :

...
 
				if (content_type == "image/png") {
					stdout.printf ("Ok\n");
				}
				else {
					stderr.printf ("No\n");
				}
 
...

par

...
 
				if (GLib.ContentType.is_a (content_type, "image/png")) {
					stdout.printf ("Ok\n");
				}
				else {
					stderr.printf ("No\n");
				}
 
...

Connaître le nom du répertoire courant

On utilise le module glib-2.0.

public class Main : Object {
 
	public static int main (string[] argv) {
		string current_dir = GLib.Environment.get_current_dir ();
 
		stdout.printf ("%s\n", current_dir);
 
		return 0;
	}
}

Pour afficher le résultat de l'exemple précédent sous forme d'uri. On doit charger en plus le module gio-2.0.

public static int main (string[] argv) {
	string current_dir = GLib.Environment.get_current_dir ();
	GLib.File file = GLib.File.new_for_path (current_dir);
 
	stdout.printf ("%s\n", file.get_uri ());
	return 0;
}

Créer un dossier

Il faut charger les modules glib-2.0 et gio-2.0.

public static int main (string[] argv) {
	// le nouveau dossier à créer
	string child_dir = "nouveau";
	string current_dir = GLib.Environment.get_current_dir ();
 
	GLib.File file = GLib.File.new_for_path (string.join ("/", current_dir, child_dir));
 
	try {
		// le dossier est créé maintenant
		file.make_directory ();
	} catch (GLib.Error e) {
		error ("%s\n", e.message);
	}
	return 0;
}

Déterminer l'origine d'une IP

Le service est désormais payant.

Cet exemple montre comment obtenir l'origine d'une IP. On doit installer utiliser les modules suivants :

  • glib-2.0
  • libsoup-2.4
  • json-glib-1.0
geoip.vala
/*
 * Compile with:
 * valac --pkg=glib-2.0 --pkg=libsoup-2.4 --pkg=json-glib-1.0 geoip.vala
 *
 * Get country code from IP address.
 *
 */
 
public class GeoIP : Object {
 
	private const string HOSTNAME = "www.telize.com";
	private string address;
 
	private Soup.URI uri;
	#if LIBSOUP_2_42
		private Soup.Session session;
	#else
		private Soup.SessionSync session;
	#endif
	private Soup.Message msg;
 
	public GeoIP () {
		/* Create Soup.URI object */
		address = "http://%s".printf (HOSTNAME);
		this.uri = new Soup.URI (address);
 
		/* Create session object */
		#if LIBSOUP_2_42
			this.session = new Soup.Session ();
		#else
			this.session = new Soup.SessionSync ();
		#endif
	}
 
	public void run (string resource) {
		string content = null;
 
		content = send_query (resource);
		if (content != null) {
			parse_json (content);
		}
	}
 
	private void parse_json (string data) {
		Json.Parser parser;
		Json.Node node;
		unowned Json.Object obj;
 
		parser = new Json.Parser ();
		try {
			parser.load_from_data (data);
		} catch (GLib.Error e) {
			stderr.printf ("Error: '%s'\n", e.message);
		}
 
		node = parser.get_root ();
		if (node.get_node_type () == Json.NodeType.OBJECT) {
			obj = node.get_object ();
			foreach (unowned string name in obj.get_members ()) {
				if (name == "country_code") {
					unowned string item;
 
					item = obj.get_string_member (name);
					stdout.printf ("%s\n", item.down ());
				}
			}
		}
	}
 
	private string send_query (string resource) {
		string content = null;
 
		this.uri.set_path ("/%s".printf (resource));
		msg = new Soup.Message.from_uri ("GET", this.uri);
		this.session.send_message (msg);
 
		#if VALA_0_22
			if (Soup.Status.OK == msg.status_code) {
		#else
			if (Soup.KnownStatusCode.OK == msg.status_code) {
		#endif
			content = (string) msg.response_body.flatten ().data;
		}
 
		return content;
	}
}
 
void main (string[] argv) {
	string path = "geoip";
 
	GeoIP ip;
 
	ip = new GeoIP ();
	ip.run (path);
}
snippet/vala.txt · Dernière modification : 2024/10/06 19:53 de olivier

Sauf mention contraire, le contenu de ce wiki est placé sous les termes de la licence suivante : Public Domain