3

Histoire d’un moteur de blog

Comme promis, je viens vous conter l’écriture de prose. N’hésitez pas à lire le code source pour en même temps.

Plusieurs contraintes s’imposaient:

Le cadre étant posé, il semblait évident que rédiger des mails serait une solution, en partie. Au moins, je répondais à tous les critères ci-dessus, avec en plus la possibilité d’utiliser des brouillons si le client mail le permet.

J’ai découvert grâce à eol l’utilisation de forward, un simple fichier de configuration qui permet de faire suivre un message reçu à une commande. C’était parfait, car n’importe quel utilisateur peut éditer ce fichier.

Restait à l’écrire maintenant. J’ai tout d’abord songé à un script shell, mais c’eût été trop facile et surtout, ça aurait manqué d’unveil et de pledge. Restait donc le C qui présente en plus l’avantage d’être rapide. Je m’y étais déjà essayé avec staticook.

Tout d’abord, pour lire le mail arrivé, il faut lire le flux d’entrée (stdin). C’est génial en C, puisque ça s’ouvre comme n’importe quel fichier:

mail = get_stream_txt(stdin);

Il faut ensuite analyser le contenu de ce mail. Première idée : définir le nom du fichier enregistré et le titre de l’article à partir du sujet du mail. Cette idée aurait permis de corriger un article en envoyant un nouveau mail avec le même sujet pour écraser le précédent. Il était même possible de définir une liste d’accès en épluchant le champ “From:”, ainsi que récupérer la date de publication avec le champ “Date:”. Toutefois, j’ai déchanté en lisant les RFC pour un mail, indiquant que ces entrées peuvent figurer (ou pas) sur plusieurs lignes. Ça aurait bien sûr été possible, mais cela rendait le code nettement plus compliqué.

J’ai donc décidé d’ignorer tous les entêtes du mail, et me concentrer sur le corps du message. C’est facile, les deux sont séparés par une ligne vide:

if ((txt = strstr(mail, "\n\n")) == NULL) {
	err(1, "%s", "Badly formatted mail, exit");
	}
txt = txt + 2; /* skip "\n\n"; */

La suite, c’est juste de l’organisation. On va dire que la première ligne c’est un mot de passe et la suite c’est le billet.

line = strsep(&txt, "\n");
if (line == NULL) {
	err(1, "%s", "no password found, exit");
}
	if (strcmp(line, pw) != 0) {
	err(1, "%s", "wrong password, exit");
}

Restait à virer les lignes vides entre le mot de passe et le billet pour pouvoir utiliser le sélecteur ::first-line en CSS:

/* we can read the rest of the body */
/* don't care of firsts \n */
while (strcspn(txt, "\n") == 0) {
	txt = txt +1;
}

Il fallait ensuite organiser les billets. J’ai oublié l’idée des noms de fichier selon le titre : j’ai décidé de faire encore plus simple, c’est à dire numéroter dans l’ordre d’apparition des billets. Ça fait une base de données on ne peut plus simple.

Ça rend même la génération d’un flux atom et d’un sitemap encore plus simples. Reprenant des fonctions de staticook, il suffisait de lister les fichiers. Puisque leur nom correspond à un nombre, c’est même très simple de les mettre dans l’ordre d’apparition.

Si un jour je modifie les modèles, je pourrais même facilement tout régénérer en les passant un par un à prose.

Restait un point sensible : les templates. J’ai pensé à faire comme staticook, lire des fichiers modèles qui seraient parsés ensuite. Pour faire plus simple, j’ai préféré définir les templates dans le config.h. C’est un peu plus fragile mais c’est tout aussi efficace.

Pour finir, je me suis amusé à créer des macros pour pledge et unveil, ça me resservira:

#define PLEDGEORDIE(prom) if (pledge(prom, NULL) == -1) { err(1,"pledge"); } 
#define UNVEILORDIE(path,perms) if (unveil(path, perms) == -1) { err(1, "unveil"); } 

Voilà, j’ai 1 seul fichier c, pas besoin de Makefile car ça ne dépend d’aucune librairie et ça utilise des mécanismes déjà disponibles dont je n’ai pas à me préoccuper.

Il reste de nombreuses améliorations possibles pour qui veut ajouter des fonctionnalités : je fais le voeux que le code source sera assez clair pour qu’il serve à d’autres. Je crois que l’intérêt de prose est justement d’être modifié :)

Tiens, une fois n’est pas coutume, si vous êtes arrivés jusqu’ici dans la lecture, vous aurez peut-être un commentaire à faire. Dans ce cas, c’est par ici:

https://3hg.fr/CHATONS/Pastebin/?d9b54df617f460ea#5dvHXDZVag7Vd9ECq146rGBretn8qdzvGB5nTMA3HRei 📧 Un commentaire?