midgard-linkdir/code/linkgen.c
2025-03-26 02:24:32 -04:00

167 lines
4.4 KiB
C

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* compile with `clang listgen.c -std=c89 -I/usr/include/libxml2 -lxml2' */
#define _XOPEN_SOURCE 500
#define _XOPEN_SOURCE_EXTENDED 500
#include <linux/limits.h>
#include <ftw.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml2/libxml/tree.h>
#include <libxml2/libxml/parser.h>
#define SMALL 1024 /* 1.0KiB */
#define BIG 524288 /* 512KiB */
char *files_list[BIG];
char *filename;
int i = 0;
regex_t regex;
int result;
void help(char program[]) {
fprintf(stderr, "Usage: %s /path/to/xml\n", program);
fprintf(stderr, "For example, %s /srv/http/users/*/site-meta.xml\n", program);
exit(EXIT_FAILURE);
}
char* get_child(const char *parent, const char *tag, xmlDocPtr doc, xmlNodePtr node) {
/* get the content of a nested element */
static char out[BIG];
xmlNodePtr child_node = NULL;
while (node != NULL) {
if (!xmlStrcmp(node->name, (const xmlChar *)parent)) {
child_node = node->children;
break;
} else {
node = node->next;
}
}
while (child_node != NULL) {
if (!xmlStrcmp(child_node->name, (const xmlChar *)tag)) {
sprintf(out, "%s", xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1));
return out;
}
child_node = child_node->next;
}
return "NOT_FOUND";
}
char* get_tag(const char* tag, xmlDocPtr doc, xmlNodePtr node) {
/* get the content of an element */
static char out[BIG];
while (node != NULL) {
if (!xmlStrcmp(node->name, (const xmlChar *)tag)) {
sprintf(out, "%s", xmlNodeListGetString(doc, node->xmlChildrenNode, 1));
return out;
}
node = node->next;
}
return "NOT_FOUND";
}
const char* gen_xhtml(const char* filename) {
/* This function is more close to being the actual main one,
it's where the HTML is generated. */
xmlDocPtr source = xmlReadFile(filename, NULL, 0);
xmlNodePtr cur = NULL;
static char out[BIG];
/* these just check if the file is really messed up */
if (source == NULL) {
fprintf(stderr, "failed to parse file\n");
xmlFreeDoc(source);
} else {
cur = xmlDocGetRootElement(source);
}
if (cur == NULL) {
fprintf(stderr, "empty\n");
xmlFreeDoc(source);
exit(EXIT_FAILURE);
}
if (xmlStrcmp(cur->name, (const xmlChar *) "linklist")) {
fprintf(stderr, "%s: root tag must be <site>\n", filename);
xmlFreeDoc(source);
exit(EXIT_FAILURE);
}
cur = cur->xmlChildrenNode;
strcat(out,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n"
" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
" <head>\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n"
" <link rel=\"stylesheet\" href=\"/assets/css/main.css\" />\n");
sprintf(out, "%s <title>Midgard Link Directory - %s/", out, get_tag("network", source, cur));
sprintf(out, "%s%s/", out, get_tag("protocol", source, cur));
sprintf(out, "%s%s</title>\n", out, get_tag("category", source, cur));
strcat(out,
" </head>\n"
" <body>\n"
" <div class=\"nav-bar\">\n"
" <h2><a href=\"/\">linkdir</a></h2>\n");
char *temp = get_tag("network", source, cur);
if (!strcmp(temp, "i2p")) {
strcat(out,
" <a href=\"/i2p/\" class=\"active\">i2p</a>\n"
" <a href=\"/tor/\">tor</a>\n"
" <a href=\"/ygg/\">ygg</a>\n");
} else if (!strcmp(temp, "tor")) {
strcat(out,
" <a href=\"/i2p/\">i2p</a>\n"
" <a href=\"/tor/\" class=\"active\">tor</a>\n"
" <a href=\"/ygg/\">ygg</a>\n");
} else if (!strcmp(temp, "ygg")) {
strcat(out,
" <a href=\"/i2p/\">i2p</a>\n"
" <a href=\"/tor/\">tor</a>\n"
" <a href=\"/ygg/\" class=\"active\">ygg</a>\n");
}
strcat(out,
" </div>\n"
" </body>\n"
"</html>\n");
return out;
}
int add_to_array(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
result = regcomp(&regex, ".*.xml$", 0);
result = regexec(&regex, fpath, 0, NULL, 0);
if (!result) {
files_list[i] = (char*) malloc (PATH_MAX);
sprintf(files_list[i], "%s", fpath);
i++;
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
help(argv[0]);
}
i = 0;
nftw(argv[1], add_to_array, 20, 0);
int file_count = i;
for (i = 0; i < file_count; i++) {
printf("[%05d]\t%s\n", i, files_list[i]);
printf("%s", gen_xhtml(files_list[i]));
}
return 0;
}