// enc: utf-8
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stddjb.h>
#include <time.h>
#include <xml.h>

#include <jrml2html.h>
#include <erreur.h>
#include <site-config.h>
#include "blog.h"
#include "blog-xml.h"
#include "rss.h"
#include "atom.h"
#include "manipulate-comments.h"
#include "comments-atom.h"
#include "comments-rss.h"

#define PROG "build-blog"

void
add_weblog_header(xmlNode *noeud_jrml)
{
	xmlNode *noeud_a, *noeud_p, *noeud_img;
	noeud_p = xmlNewNode(NULL, "p");
	xmlAddChild(noeud_jrml, noeud_p);
	xmlAddChild(noeud_p, xmlNewText("Billets — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL RSS_FILE);
	xmlSetProp(noeud_a, "rel", "alternate");
	xmlSetProp(noeud_a, "type", "application/rss+xml");
	xmlSetProp(noeud_a, "title", "RSS");
	noeud_img = xmlNewNode(NULL, "img");
	xmlAddChild(noeud_a, noeud_img);
	xmlSetProp(noeud_img, "src", URL_XML_PNG);
	xmlSetProp(noeud_img, "alt", "XML");
	xmlAddChild(noeud_p, xmlNewText(" ("));
	xmlNewChild(noeud_p, NULL, "abbr", "RSS");
	xmlAddChild(noeud_p, xmlNewText(" 1.0)"));

	xmlAddChild(noeud_p, xmlNewText(" — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL ATOM_FILE);
	xmlSetProp(noeud_a, "rel", "alternate");
	xmlSetProp(noeud_a, "type", "application/atom+xml");
	xmlSetProp(noeud_a, "title", "Atom");
	noeud_img = xmlNewNode(NULL, "img");
	xmlAddChild(noeud_a, noeud_img);
	xmlSetProp(noeud_img, "src", URL_XML_PNG);
	xmlSetProp(noeud_img, "alt", "XML");
	xmlAddChild(noeud_p, xmlNewText(" (Atom 1.0)"));

	noeud_p = xmlNewNode(NULL, "p");
	xmlAddChild(noeud_jrml, noeud_p);
	xmlAddChild(noeud_p, xmlNewText("Commentaires — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL COMMENTS_RSS_FILE);
	xmlSetProp(noeud_a, "type", "application/rss+xml");
	xmlSetProp(noeud_a, "title", "RSS (commentaires)");
	noeud_img = xmlNewNode(NULL, "img");
	xmlAddChild(noeud_a, noeud_img);
	xmlSetProp(noeud_img, "src", URL_XML_PNG);
	xmlSetProp(noeud_img, "alt", "XML");
	xmlAddChild(noeud_p, xmlNewText(" ("));
	xmlNewChild(noeud_p, NULL, "abbr", "RSS");
	xmlAddChild(noeud_p, xmlNewText(" 1.0)"));

	xmlAddChild(noeud_p, xmlNewText(" — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL COMMENTS_ATOM_FILE);
	xmlSetProp(noeud_a, "type", "application/atom+xml");
	xmlSetProp(noeud_a, "title", "Atom");
	noeud_img = xmlNewNode(NULL, "img");
	xmlAddChild(noeud_a, noeud_img);
	xmlSetProp(noeud_img, "src", URL_XML_PNG);
	xmlSetProp(noeud_img, "alt", "XML");
	xmlAddChild(noeud_p, xmlNewText(" (Atom 1.0)"));

	noeud_p = xmlNewNode(NULL, "p");
	xmlAddChild(noeud_jrml, noeud_p);

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlAddChild(noeud_a, xmlNewText("Index de toutes les entrées"));
	xmlSetProp(noeud_a, "href", BLOG_URL WEBLOG_INDEX_FILE);

	xmlAddChild(noeud_p, xmlNewText(" — "));
	
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlAddChild(noeud_a, xmlNewText("Index des catégories"));
	xmlSetProp(noeud_a, "href", CATEGORIES_URL);

	xmlAddChild(noeud_p, xmlNewText(" — "));
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlAddChild(noeud_a, xmlNewText("Calendrier"));
	xmlSetProp(noeud_a, "href", BLOG_URL CALENDAR_FILE);
}

void
add_fils(xmlNode *node)
{
	xmlNode *noeud_h2, *noeud_li, *noeud_a, *noeud_ul;
	noeud_h2 = xmlNewNode(NULL, "h2");
	xmlAddChild(node, noeud_h2);
	xmlAddChild(noeud_h2, xmlNewText("Enfilades"));

	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(node, noeud_ul);
	noeud_li = xmlNewNode(NULL, "li");
	xmlAddChild(noeud_ul, noeud_li);
	xmlAddChild(noeud_li, xmlNewText("Billets : "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_li, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL RSS_FILE);
	xmlSetProp(noeud_a, "rel", "alternate");
	xmlSetProp(noeud_a, "type", "application/rss+xml");
	xmlSetProp(noeud_a, "title", "RSS");
	xmlAddChild(noeud_a, xmlNewText("RSS 1.0"));
	xmlAddChild(noeud_li, xmlNewText(" — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_li, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL ATOM_FILE);
	xmlSetProp(noeud_a, "rel", "alternate");
	xmlSetProp(noeud_a, "type", "application/atom+xml");
	xmlSetProp(noeud_a, "title", "Atom");
	xmlAddChild(noeud_a, xmlNewText("Atom 1.0"));

	noeud_li = xmlNewNode(NULL, "li");
	xmlAddChild(noeud_ul, noeud_li);
	xmlAddChild(noeud_li, xmlNewText("Commentaires : "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_li, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL COMMENTS_RSS_FILE);
	xmlSetProp(noeud_a, "type", "application/rss+xml");
	xmlSetProp(noeud_a, "title", "RSS (commentaires)");
	xmlAddChild(noeud_a, xmlNewText("RSS 1.0"));
	xmlAddChild(noeud_li, xmlNewText(" — "));

	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_li, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL COMMENTS_ATOM_FILE);
	xmlSetProp(noeud_a, "type", "application/atom+xml");
	xmlSetProp(noeud_a, "title", "Atom (commentaires)");
	xmlAddChild(noeud_a, xmlNewText("Atom 1.0"));
}

xmlNode *
compute_filmlog(void)
{
	xmlDoc *doc_filmlog;
	xmlNode *noeud_ul, *noeud;
	int i;
	noeud_ul = xmlNewNode(NULL, "ul");
	doc_filmlog = xmlReadFile(FILMLOG_FILE, NULL, XML_PARSE_FLAGS);
	if (!doc_filmlog)
		strerr_diefu1x(100, "xmlReadFile " FILMLOG_FILE);
	noeud = xmlDocGetRootElement(doc_filmlog);
	for(noeud=noeud->children;noeud;noeud=noeud->next) {
		if (noeud->type != XML_ELEMENT_NODE) continue;
		if (strcmp(noeud->name, "ul")) continue;
		if (strcmp(xmlGetProp(noeud, "id"), "filmlog")) continue;
		break;
	}
	if (!noeud)
		strerr_diefu1x(100, "find filmlog");
	for(i=0,noeud=noeud->children;noeud &&
		(i<NUMBER_OF_MOVIES_IN_FILMLOG_SUMMARY);
		noeud=noeud->next) {
		if (noeud->type != XML_ELEMENT_NODE) continue;
		if (strcmp(noeud->name, "li")) continue;
		i++;
		xmlAddChild(noeud_ul, xmlCopyNode(noeud, 1));
	}
	
	xmlFreeDoc(doc_filmlog);
	return noeud_ul;
}

xmlNode *
compute_booklog(void)
{
	xmlDoc *doc_booklog;
	xmlNode *noeud_ul, *noeud;
	int i;
	noeud_ul = xmlNewNode(NULL, "ul");
	doc_booklog = xmlReadFile(BOOKLOG_FILE, NULL, XML_PARSE_FLAGS);
	if (!doc_booklog)
		strerr_diefu1x(100, "xmlReadFile " BOOKLOG_FILE);
	noeud = xmlDocGetRootElement(doc_booklog);
	for(noeud=noeud->children;noeud;noeud=noeud->next) {
		char *id;
		if (noeud->type != XML_ELEMENT_NODE) continue;
		if (strcmp(noeud->name, "ul")) continue;
		id = xmlGetProp(noeud, "id");
		if (!id) continue;
		if (strcmp(id, "booklog")) continue;
		break;
	}
	if (!noeud)
		strerr_diefu1x(100, "find booklog");
	for(i=0,noeud=noeud->children;noeud &&
		(i<NUMBER_OF_BOOKS_IN_BOOKLOG_SUMMARY);
		noeud=noeud->next) {
		if (noeud->type != XML_ELEMENT_NODE) continue;
		if (strcmp(noeud->name, "li")) continue;
		i++;
		xmlAddChild(noeud_ul, xmlCopyNode(noeud, 1));
	}
	
	xmlFreeDoc(doc_booklog);
	return noeud_ul;
}

void
add_filmlog(xmlNode *node)
{
	static xmlNode *noeud_filmlog_ul = NULL;	
	xmlNode *noeud_h3, *noeud_a;
	noeud_h3 = xmlNewNode(NULL, "h3");
	xmlAddChild(node, noeud_h3);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h3, noeud_a);
	xmlSetProp(noeud_a, "href", URL_FILMLOG);
	xmlAddChild(noeud_a, xmlNewText("filmlog"));
	if (!noeud_filmlog_ul)
		noeud_filmlog_ul = compute_filmlog();
	xmlAddChild(node, xmlCopyNode(noeud_filmlog_ul, 1));
}

void
add_booklog(xmlNode *node)
{
	static xmlNode *noeud_booklog_ul = NULL;	
	xmlNode *noeud_h3, *noeud_a;
	noeud_h3 = xmlNewNode(NULL, "h3");
	xmlAddChild(node, noeud_h3);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h3, noeud_a);
	xmlSetProp(noeud_a, "href", URL_BOOKLOG);
	xmlAddChild(noeud_a, xmlNewText("booklog"));
	if (!noeud_booklog_ul)
		noeud_booklog_ul = compute_booklog();
	xmlAddChild(node, xmlCopyNode(noeud_booklog_ul, 1));
}

void
add_culture(xmlNode *node)
{
	xmlNode *noeud_h2, *noeud_a;
	noeud_h2 = xmlNewNode(NULL, "h2");
	xmlAddChild(node, noeud_h2);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h2, noeud_a);
	xmlSetProp(noeud_a, "href", URL_CULTURE);
	xmlAddChild(noeud_a, xmlNewText("Culture"));
	add_booklog(node);
	add_filmlog(node);
}

char *
mois_of_prefix(char *prefix)
{
	static stralloc mois = GEN_ALLOC_ZERO;
	unsigned int mois_number;
	char *mois_str;
	char *nom = NULL;
	if (strlen(prefix) != 7) return prefix;
	mois_str = prefix+5;
	if (mois_str[uint_scan(mois_str, &mois_number)]) return prefix;
	switch (mois_number) {
		case 1: nom = "janvier"; break;
		case 2: nom = "février"; break;
		case 3: nom = "mars"; break;
		case 4: nom = "avril"; break;
		case 5: nom = "mai"; break;
		case 6: nom = "juin"; break;
		case 7: nom = "juillet"; break;
		case 8: nom = "août"; break;
		case 9: nom = "septembre"; break;
		case 10: nom = "octobre"; break;
		case 11: nom = "novembre"; break;
		case 12: nom = "décembre"; break;
	}
	if (!nom) return prefix;
	if (!(stralloc_copys(&mois, nom) 
		&& stralloc_cats(&mois, " ") 
		&& stralloc_catb(&mois, prefix, 4)
		&& stralloc_0(&mois))) nomem();
	return mois.s;
}

void
add_archives(xmlNode *node)
{
	xmlNode *noeud_h2, *noeud_li, *noeud_a, *noeud_ul;
	weblog_part_s *part;
	static stralloc url = GEN_ALLOC_ZERO;
	int i;
	noeud_h2 = xmlNewNode(NULL, "h2");
	xmlAddChild(node, noeud_h2);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h2, noeud_a);
	xmlSetProp(noeud_a, "href", BLOG_URL_FROM_BASE CALENDAR_FILE);
	xmlAddChild(noeud_a, xmlNewText("Archives"));
	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(node, noeud_ul);
	for(i = weblog_parts.count-1;(i >= 0);i--) {
		part = weblog_parts.part+i;
		noeud_li = xmlNewNode(NULL, "li");
		noeud_a = xmlNewNode(NULL, "a");
		xmlAddChild(noeud_ul, noeud_li);
		xmlAddChild(noeud_li, noeud_a);
		xmlAddChild(noeud_a,
			xmlNewText(mois_of_prefix(part->date_prefix)));
		if (!(stralloc_copys(&url, BLOG_URL) &&
			stralloc_cats(&url, part->date_prefix) &&
			stralloc_cats(&url, ".html") &&
			stralloc_0(&url))) nomem();
		xmlSetProp(noeud_a, "href", url.s);
	}
}

void
add_index(xmlNode *node)
{
	xmlNode *noeud_h2, *noeud_a;
	noeud_h2 = xmlNewNode(NULL, "h2");
	xmlAddChild(node, noeud_h2);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h2, noeud_a);
	xmlAddChild(noeud_a, xmlNewText("Index de toutes les entrées"));
	xmlSetProp(noeud_a, "href", BLOG_URL WEBLOG_INDEX_FILE);
}

void
add_categories(xmlNode *node)
{
	xmlNode *noeud_h2, *noeud_li, *noeud_a, *noeud_ul;
	weblog_category_s *category;
	static stralloc url = GEN_ALLOC_ZERO;
	unsigned int i;
	char fmt[FMT_ULONG];
	noeud_h2 = xmlNewNode(NULL, "h2");
	xmlAddChild(node, noeud_h2);
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_h2, noeud_a);
	xmlSetProp(noeud_a, "href", CATEGORIES_URL);
	xmlAddChild(noeud_a, xmlNewText("Catégories"));
	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(node, noeud_ul);
	for(i=0;i<weblog_categories.count;i++) {
		category = weblog_categories.category+i;
		noeud_li = xmlNewNode(NULL, "li");
		xmlAddChild(noeud_ul, noeud_li);
		noeud_a = xmlNewNode(NULL, "a");
		xmlAddChild(noeud_li, noeud_a);
		xmlAddChild(noeud_a, xmlNewText(category->title));
		if (!(stralloc_copys(&url, CATEGORIES_URL) &&
			stralloc_cats(&url, category->id) &&
			stralloc_cats(&url, ".html") &&
			stralloc_0(&url))) nomem();
		xmlSetProp(noeud_a, "href", url.s);
		xmlAddChild(noeud_a, xmlNewText(" ("));
		fmt[fmt_uint(fmt, category->entries.count)]=0;
		xmlAddChild(noeud_a, xmlNewText(fmt));
		xmlAddChild(noeud_a, xmlNewText(")"));
	}
}

void
add_weblog_sidebar(jrml_file_s *jrml)
{
	xmlNode *noeud_jrml, *noeud_sidebar;
	noeud_jrml = xmlDocGetRootElement(jrml->document);
	noeud_sidebar = xmlNewNode(NULL, "div");
	jrml->noeud_sidebar = noeud_sidebar;
	xmlSetProp(noeud_sidebar, "id", "sidebar");
	add_fils(noeud_sidebar);
	add_categories(noeud_sidebar);
	add_culture(noeud_sidebar);
	add_archives(noeud_sidebar);
	add_index(noeud_sidebar);
}

void
build_index(void)
{
	jrml_file_s jrml;
	xmlNode *noeud_jrml;
	int i;
	
	jrml.path = BLOG_URL_FROM_BASE;
	jrml.flags = FLAG_ADD_BLOG_ALTERNATE_LINKS;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_TITLE);
	add_weblog_sidebar(&jrml);
	for(i = weblog_entries.count-1;(i >= 0);i--)
		if (weblog_entries.entry[i].in_index)
			dump_entry(noeud_jrml, weblog_entries.entry+i,
				WEBLOG_ROOT);
	xml_save_atomic(jrml2html(&jrml), BLOGWWW "index.html");
}

void
build_preview(void)
{
	jrml_file_s jrml;
	xmlNode *noeud_jrml;
	int i;
	
	jrml.path = BLOG_URL_FROM_BASE "preview.html";
	jrml.flags = 0;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_TITLE);
	add_weblog_sidebar(&jrml);
	xmlNewChild(noeud_jrml, NULL, "p",
		"Cette page me sert à prévisualiser "
		"les entrées en cours d'écriture.");
	for(i = weblog_entries.count-1;(i >= 0);i--)
		if (!weblog_entries.entry[i].ok)
			dump_entry(noeud_jrml, weblog_entries.entry+i,
				WEBLOG_PREVIEW);
	xml_save_atomic(jrml2html(&jrml), BLOGWWW "preview.html");
}

void
build_part(weblog_part_s *partie)
{
	static stralloc path = GEN_ALLOC_ZERO;
	static stralloc filename = GEN_ALLOC_ZERO;
	jrml_file_s jrml;
	xmlNode *noeud_jrml, *noeud_p, *noeud_a;
	static stralloc message = GEN_ALLOC_ZERO;
	int i;
	char *mois;

	if (!(stralloc_copys(&path, BLOG_URL_FROM_BASE) &&
		stralloc_cats(&path, partie->date_prefix) &&
		stralloc_cats(&path, ".html") &&
		stralloc_0(&path))) nomem();
	
	jrml.path = path.s;
	jrml.flags = FLAG_ADD_BLOG_ALTERNATE_LINKS;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_TITLE);
	add_weblog_sidebar(&jrml);
	noeud_p = xmlNewNode(NULL, "p");
	xmlAddChild(noeud_jrml, noeud_p);
	mois = mois_of_prefix(partie->date_prefix);
	if (!(stralloc_copys(&message, "Cette page ne contient que les "
		"entrées du mois ") &&
		stralloc_cats(&message, (mois[0] == 'a') ? "d'" : "de ") &&
		stralloc_cats(&message, mois) &&
		stralloc_cats(&message, ". Les entrées les plus récentes "
		"se trouvent ") &&
		stralloc_0(&message))) nomem();
	xmlAddChild(noeud_p, xmlNewText(message.s));
	noeud_a = xmlNewNode(NULL, "a");
	xmlAddChild(noeud_p, noeud_a);
	xmlAddChild(noeud_a, xmlNewText("là"));
	xmlSetProp(noeud_a, "href", BLOG_URL);
	xmlAddChild(noeud_p, xmlNewText("."));

	for(i = weblog_entries.count-1;(i >= 0);i--)
		if (!strcmp(partie->date_prefix, 
			weblog_entries.entry[i].date_prefix))
			dump_entry(noeud_jrml, weblog_entries.entry+i,
				WEBLOG_PART);
	if (!(stralloc_copys(&filename, BLOGWWW) &&
		stralloc_cats(&filename, partie->date_prefix) &&
		stralloc_cats(&filename, ".html") && 
		stralloc_0(&filename))) nomem();
	xml_save_atomic(jrml2html(&jrml), filename.s);
}

void
build_part_index(weblog_part_s *partie)
{
	int fd;
	unsigned int i;
	char blog_id[FMT_BLOG_ID];
	static stralloc filename = GEN_ALLOC_ZERO;
	static stralloc filename_new = GEN_ALLOC_ZERO;
	buffer buffer_index;
	char buf[BUFLEN];
	if (!(stralloc_copys(&filename_new, BLOGDATA "index-") && 
		stralloc_cats(&filename_new, partie->date_prefix) &&
		stralloc_cats(&filename_new, ".new") &&
		stralloc_0(&filename_new))) nomem();
	if (!(stralloc_copys(&filename, BLOGDATA "index-") && 
		stralloc_cats(&filename, partie->date_prefix) &&
		stralloc_0(&filename))) nomem();
	fd = creat(filename_new.s, 0666);
	if (fd == -1)
		strerr_diefu2x(111, "creat ", filename_new.s);
	buffer_init(&buffer_index, &buffer_unixwrite, fd, buf, BUFLEN);
	for (i = 0;i<weblog_entries.count;i++)
		if (!strcmp(partie->date_prefix, 
			weblog_entries.entry[i].date_prefix)) {
			fmt_blog_id(blog_id, weblog_entries.entry[i].number);
			buffer_puts(&buffer_index, blog_id);
			buffer_puts(&buffer_index, "\n");
		}
	buffer_flush(&buffer_index);
	close(fd);

	if (rename(filename_new.s, filename.s)==-1)
		strerr_diefu1x(111, "rename");
}

void
build_comment_directory(weblog_entry_s *entry)
{
	static stralloc ch = GEN_ALLOC_ZERO;
	static stralloc ch2 = GEN_ALLOC_ZERO;
	static stralloc directory = GEN_ALLOC_ZERO;
	char blog_id[FMT_BLOG_ID];
	char id[FMT_ULONG];
	char buf[BUFLEN];
	buffer buffer_w;
	int fd;
	fmt_blog_id(blog_id, entry->number);
	id[fmt_uint(id, entry->number)]=0;
	if (!(stralloc_copys(&directory, BLOGCOMMENTS) &&
		stralloc_cats(&directory, blog_id) &&
		stralloc_cats(&directory, "/") &&
		stralloc_0(&directory))) nomem();
	mkdir(directory.s, 0777);
	if (!(stralloc_copys(&ch, directory.s) &&
		stralloc_cats(&ch, "titre.new") && stralloc_0(&ch))) nomem();
	if (!(stralloc_copys(&ch2, directory.s) &&
		stralloc_cats(&ch2, "titre") && stralloc_0(&ch2))) nomem();
	if ((fd = creat(ch.s, 0666)) == -1)
		strerr_diefu2x(111, "creat ", ch.s);
	buffer_init(&buffer_w, &buffer_unixwrite, fd, buf, BUFLEN);
	buffer_puts(&buffer_w, entry->title);
	buffer_putsflush(&buffer_w, "\n");
	close(fd);
	if (rename(ch.s, ch2.s)==-1)
		strerr_diefu1x(111, "rename");

	if (!(stralloc_copys(&ch, directory.s) &&
		stralloc_cats(&ch, "url.new") && stralloc_0(&ch))) nomem();
	if (!(stralloc_copys(&ch2, directory.s) &&
		stralloc_cats(&ch2, "url") && stralloc_0(&ch2))) nomem();
	if ((fd = creat(ch.s, 0666)) == -1)
		strerr_diefu2x(111, "creat ", ch.s);
	buffer_init(&buffer_w, &buffer_unixwrite, fd, buf, BUFLEN);
	buffer_puts(&buffer_w, BLOG_URL);
	buffer_puts(&buffer_w, entry->date_prefix);
	buffer_puts(&buffer_w, ".html");
	buffer_puts(&buffer_w, "#e.");
	buffer_puts(&buffer_w, id);
	buffer_putsflush(&buffer_w, "\n");
	close(fd);
	if (rename(ch.s, ch2.s)==-1)
		strerr_diefu1x(111, "rename");
}

void
build_weblog_index(void)
{
	jrml_file_s jrml;
	xmlNode *noeud_jrml;
	int i;
	weblog_entry_s *entry;
	xmlNode *noeud_ul, *noeud_li, *noeud_a;
	char id[FMT_ULONG];
	static stralloc url = GEN_ALLOC_ZERO;
	
	jrml.path = BLOG_URL_FROM_BASE WEBLOG_INDEX_FILE;
	jrml.flags = FLAG_ADD_BLOG_ALTERNATE_LINKS;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_TITLE);
	add_weblog_sidebar(&jrml);
	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(noeud_jrml, noeud_ul);
	for(i = weblog_entries.count-1;(i >= 0);i--) {
		entry = weblog_entries.entry+i;
		if (!entry->ok) continue;
		noeud_li = xmlNewNode(NULL, "li");
		xmlAddChild(noeud_ul, noeud_li);
		xmlAddChild(noeud_li, xmlNewText(entry->date));
		xmlAddChild(noeud_li, xmlNewText(" : "));
		noeud_a = xmlNewNode(NULL, "a");
		xmlAddChild(noeud_li, noeud_a);
		id[fmt_uint(id, entry->number)]=0;
		if (!(stralloc_copys(&url, BLOG_URL) &&
			stralloc_cats(&url, entry->date_prefix) &&
			stralloc_cats(&url, ".html#e.") &&
			stralloc_cats(&url, id) &&
			stralloc_0(&url))) nomem();
		xmlSetProp(noeud_a, "href", url.s);
		xmlAddChild(noeud_a, xmlNewText(entry->title));
	}
	xml_save_atomic(jrml2html(&jrml), BLOGWWW WEBLOG_INDEX_FILE);
}

void
build_calendar(void)
{
	jrml_file_s jrml;
	xmlNode *noeud_jrml;
	int i;
	weblog_part_s *part;
	xmlNode *noeud_ul, *noeud_li, *noeud_a;
	static stralloc url = GEN_ALLOC_ZERO;
	
	jrml.path = BLOG_URL_FROM_BASE CALENDAR_FILE;
	jrml.flags = FLAG_ADD_BLOG_ALTERNATE_LINKS;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_TITLE);
	add_weblog_sidebar(&jrml);
	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(noeud_jrml, noeud_ul);
	for(i = weblog_parts.count-1;(i >= 0);i--) {
		part = weblog_parts.part+i;
		noeud_li = xmlNewNode(NULL, "li");
		noeud_a = xmlNewNode(NULL, "a");
		xmlAddChild(noeud_ul, noeud_li);
		xmlAddChild(noeud_li, noeud_a);
		xmlAddChild(noeud_a,
			xmlNewText(mois_of_prefix(part->date_prefix)));
		if (!(stralloc_copys(&url, BLOG_URL) &&
			stralloc_cats(&url, part->date_prefix) &&
			stralloc_cats(&url, ".html") &&
			stralloc_0(&url))) nomem();
		xmlSetProp(noeud_a, "href", url.s);
	}
	xml_save_atomic(jrml2html(&jrml), BLOGWWW CALENDAR_FILE);
}

void
build_comment_directories(void)
{
	unsigned int i;
	for (i=0;i<weblog_entries.count;i++)
		build_comment_directory(weblog_entries.entry+i);
}

void
build_parts(void)
{
	unsigned int i;
	for (i=0;i<weblog_parts.count;i++) {
		build_part(weblog_parts.part+i);
		build_part_index(weblog_parts.part+i);
	}
}

void
build_category(weblog_category_s *category)
{
	static stralloc path = GEN_ALLOC_ZERO;
	static stralloc filename = GEN_ALLOC_ZERO;
	jrml_file_s jrml;
	xmlNode *noeud_jrml;
	int i;
	weblog_entry_s *entry;

	if (!(stralloc_copys(&path, CATEGORIES_URL_FROM_BASE) &&
		stralloc_cats(&path, category->id) &&
		stralloc_cats(&path, ".html") &&
		stralloc_0(&path))) nomem();
	
	jrml.path = path.s;
	jrml.flags = 0;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", category->title);
	add_weblog_sidebar(&jrml);

	for(i = category->entries.count-1;(i >= 0);i--) {
		entry = category->entries.entry_ptr[i];
		if (!entry->ok) continue;
		dump_entry(noeud_jrml, entry,
			WEBLOG_CATEGORY);
	}
	if (!(stralloc_copys(&filename, BLOGCATEGORIES) &&
		stralloc_cats(&filename, category->id) &&
		stralloc_cats(&filename, ".html") && 
		stralloc_0(&filename))) nomem();
	xml_save_atomic(jrml2html(&jrml), filename.s);
}


void
build_categories_index(void)
{
	jrml_file_s jrml;
	xmlNode *noeud_jrml, *noeud_ul, *noeud_li, *noeud_a;
	weblog_category_s *category;
	unsigned int i;
	static stralloc url = GEN_ALLOC_ZERO;

	jrml.path = CATEGORIES_URL_FROM_BASE;
	jrml.flags = 0;
	jrml.noeud_nav_ul = NULL;
	jrml.noeud_sidebar = NULL;
	jrml.document = jrml_new();
	noeud_jrml = xmlNewNode(NULL, "jrml");
	xmlDocSetRootElement(jrml.document, noeud_jrml);
	xmlSetProp(noeud_jrml, "title", WEBLOG_CATEGORIES_TITLE);
	add_weblog_sidebar(&jrml);

	noeud_ul = xmlNewNode(NULL, "ul");
	xmlAddChild(noeud_jrml, noeud_ul);
	for(i=0;i<weblog_categories.count;i++) {
		category = weblog_categories.category+i;
		noeud_li = xmlNewNode(NULL, "li");
		xmlAddChild(noeud_ul, noeud_li);
		noeud_a = xmlNewNode(NULL, "a");
		xmlAddChild(noeud_li, noeud_a);
		xmlAddChild(noeud_a, xmlNewText(category->title));
		if (!(stralloc_copys(&url, CATEGORIES_URL) &&
			stralloc_cats(&url, category->id) &&
			stralloc_cats(&url, ".html") &&
			stralloc_0(&url))) nomem();
		xmlSetProp(noeud_a, "href", url.s);
	}
	xml_save_atomic(jrml2html(&jrml), BLOGCATEGORIES "index.html");
}

void
build_categories(void)
{
	unsigned int i;
	for (i=0;i<weblog_categories.count;i++)
		build_category(weblog_categories.category + i);
}

void
build_comments_feeds(void)
{
	weblog_comment_alloc comments = GEN_ALLOC_ZERO;
	prepare_comments_data(&comments);
	build_comments_atom(&comments);
	build_comments_rss(&comments);
}

int
main()
{
	read_data();
	build_comment_directories();
	build_index();
	build_rss();
	build_atom();
	build_parts();
	build_preview();
	build_weblog_index();
	build_categories();
	build_categories_index();
	build_calendar();
	build_comments_feeds();
	if (creat(BLOGTIMESTAMP, 0666) == -1)
		strerr_diefu2x(100, "creat", BLOGTIMESTAMP);
	return 0;
}

// FIXME : grosses fuites de memoire...

