mirror of
https://forge.fsky.io/midgard/linkdir.git
synced 2025-04-18 16:23:42 -05:00
167 lines
4.4 KiB
C
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(®ex, ".*.xml$", 0);
|
|
result = regexec(®ex, 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;
|
|
}
|