added rss support

This commit is contained in:
Your Name 2025-02-20 12:58:50 +03:00
parent 3f54bd1a04
commit b7420af3ad
2 changed files with 85 additions and 13 deletions

View File

@ -2,6 +2,7 @@
#define ROOT "8img_dir"
#define DB ROOT"/db"
/* Html generator */
#define CSS "style.css"
#define LOGO "logo.png"
@ -10,3 +11,10 @@
#define TITLE "8img gallery"
#define POST_PER_PAGE 5
/* RSS generator */
#define LINK "mygallery.com"
#define XML_FILE "index.xml"
#define LANGUAGE "en-US"
#define MAX_POST_COUNT 25

90
img.c
View File

@ -5,11 +5,15 @@
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <time.h>
#include "config.h"
struct DB_STR {
char *filename;
struct stat stat;
char stat_filled;
char **tags;
size_t size;
@ -56,7 +60,7 @@ void copy(const char *src, const char *dst) {
if (ifp == NULL)
exit(1);
FILE *ofp = file_open(dst, "a");
FILE *ofp = file_open(dst, "w");
if (ofp == NULL) {
fclose(ifp);
exit(1);
@ -166,7 +170,6 @@ struct DB_STR *new_db_value(char *str) {
if (db == NULL)
return NULL;
/* Filename */
char *tok = strtok(str, " ");
char *ptr = strrchr(tok, '\n');
@ -177,7 +180,6 @@ struct DB_STR *new_db_value(char *str) {
if (db->filename == NULL)
goto NDV_CLOSE;
/* Tags */
tok = strtok(NULL, " ");
if (tok == NULL)
@ -203,6 +205,15 @@ struct DB_STR *new_db_value(char *str) {
}
}
/* Stats */
char new_path[PATH_MAX + 1];
snprintf(new_path, sizeof(new_path) - 1, "%s/%s", ROOT, db->filename);
if (stat(new_path, &db->stat) < 0)
fprintf(stderr, "8img: stat: %s: %s\n", db->filename, strerror(errno));
else
db->stat_filled = 1;
return db;
@ -255,8 +266,8 @@ RDB_CLOSE:
return db;
}
struct DB_STR *build_html(FILE *fp, const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db, const size_t page, const size_t pages) {
fprintf(fp, "<html>\n<head>\n<link rel='stylesheet' href='%s'>\n<title>%s</title>\n</head>\n<body>\n<a href='index.html'><img id='logo' src='%s'></a><h1 id='desc'>%s<br>%s/p%zu</h1>\n", CSS, TITLE, LOGO, DESC, file, page);
struct DB_STR *build_html_page(FILE *fp, const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db, const size_t page, const size_t pages) {
fprintf(fp, "<html>\n<head>\n<link rel='stylesheet' href='%s'>\n<title>%s</title>\n</head>\n<body>\n<a href='index.html'><center><img id='logo' src='%s'></center></a>\n<h1 id='desc'>%s<br>%s/p%zu</h1>\n", CSS, TITLE, LOGO, DESC, file, page);
/* Tags */
fputs("<center><div class='alltags'>\n<a href='index.html'>all</a>", fp);
@ -282,7 +293,7 @@ struct DB_STR *build_html(FILE *fp, const char *file, const struct UNIQ_TAGS ut,
}
}
fprintf(fp, "<a href='%s'>\n<img src='%s' alt='%s'></a><br>\n>", p->filename, p->filename, p->filename);
fprintf(fp, "<a href='%s'>\n<img src='%s' alt='%s'></a><br>\n| %s<br>\n>", p->filename, p->filename, p->filename, ctime(&p->stat.st_ctime));
for (size_t i = 0; i < p->size; i++)
fprintf(fp, "<a href='%s.html'> %s</a>", p->tags[i], p->tags[i]);
@ -290,7 +301,7 @@ struct DB_STR *build_html(FILE *fp, const char *file, const struct UNIQ_TAGS ut,
p = i;
images++;
if (images >= POST_PER_PAGE)
if (images == POST_PER_PAGE)
break;
}
@ -321,7 +332,7 @@ struct DB_STR *build_html(FILE *fp, const char *file, const struct UNIQ_TAGS ut,
return p;
}
void build(const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db) {
void build_html(const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db) {
size_t page = 0;
size_t pages = 0;
@ -352,17 +363,17 @@ void build(const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db) {
while (1) {
char new_path[PATH_MAX + 1];
if (page == 0)
snprintf(new_path, sizeof(new_path), "%s/%s.html", ROOT, file);
snprintf(new_path, sizeof(new_path) - 1, "%s/%s.html", ROOT, file);
else
snprintf(new_path, sizeof(new_path), "%s/%s-%zu.html", ROOT, file, page);
snprintf(new_path, sizeof(new_path) - 1, "%s/%s-%zu.html", ROOT, file, page);
FILE *fp = file_open(new_path, "w");
if (fp == NULL)
return;
/* Builders */
p = build_html(fp, file, ut, p, page, pages);
p = build_html_page(fp, file, ut, p, page, pages);
if (p == NULL) {
fclose(fp);
break;
@ -373,6 +384,58 @@ void build(const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db) {
}
}
void build_xml(const char *file, struct DB_STR *db) {
char new_path[PATH_MAX + 1];
snprintf(new_path, sizeof(new_path) - 1, "%s/%s", ROOT, file);
FILE *fp = file_open(new_path, "w");
if (fp == NULL)
return;
/* Header */
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n<rss version='2.0' xmlns:atom='http://www.w3.org/2005/Atom'>\n<channel>\n\t<atom:link href='%s' rel='self' type='application/rss+xml' />\n\t<title>%s</title>\n\t<link>%s</link>\n\t<description>%s</description>\n\t<language>%s</language>\n", LINK, TITLE, LINK, DESC, LANGUAGE);
/* Content */
size_t count = 0;
struct DB_STR *p = db;
while (p) {
struct DB_STR *i = p->next;
/* Link to file */
size_t size = sizeof(LINK) + strlen(p->filename) + 1;
char *new_link = malloc(size + 1);
if (new_link == NULL) {
fprintf(stdout, "8img: malloc: %s: %s\n", p->filename, strerror(errno));
continue;
}
if (LINK[sizeof(LINK) - 1] == '/')
snprintf(new_link, size, "%s%s", LINK, p->filename);
else
snprintf(new_link, size, "%s/%s", LINK, p->filename);
/* Post */
fprintf(fp, "\n<item>\n\t<title>%s</title>\n\t<link>%s</link>\n\t<guid>%s</guid>\n\t<pubDate>\n\t\t%s\t</pubDate>\n\t<description><![CDATA[\n\t\t<p><img src='%s' alt='plup'></p>\n\t\t<p>", p->filename, new_link, new_link, ctime(&p->stat.st_ctime), new_link);
/* Tags */
for (size_t i = 0; i < p->size; i++)
fprintf(fp, "<a href='%s.html'> %s</a>&nbsp; ", p->tags[i], p->tags[i]);
fputs("</p>\n\t]]></description>\n</item>", fp);
free(new_link);
if (count == MAX_POST_COUNT)
break;
p = i;
}
fputs("\n</channel>\n</rss>", fp);
fclose(fp);
}
char **uniq(struct DB_STR *db, size_t *uniq_size) {
char **uniq_tag = malloc(sizeof(char *));
if (uniq_tag == NULL)
@ -424,9 +487,10 @@ void rebuild(void) {
struct UNIQ_TAGS ut = {.tags = uniq_tag, .size = uniq_size};
for (size_t i = 0; i < uniq_size; i++)
build(uniq_tag[i], ut, db);
build_html(uniq_tag[i], ut, db);
build("index", ut, db);
build_html("index", ut, db);
build_xml(XML_FILE, db);
}
else