====== Vala ======
Vala est un langage de programmation compilé, qui réutilise la « plateforme » [[https://developer.gnome.org/gobject/stable/|GObject]] du projet [[http://www.gnome.org/|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.
/*
* 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 [[https://developer.gnome.org/glib/stable/glib-regex-syntax.html|page]] (Cf. **Named subpatterns**).
/**
* 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=(?Pvideo[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**.
/**
* 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 [[https://developer.gnome.org/gio/stable/gio-GContentType.html#g-content-type-is-a|g_content_type_is_a]].
Depuis Vala >= 0.12 [[http://www.valadoc.org/#!api=gio-2.0/GLib.g_content_type_is_a|GLib.g_content_is_a]] est obsolète, on doit plutôt utiliser [[http://www.valadoc.org/#!api=gio-2.0/GLib.ContentType.is_a|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
/*
* 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);
}