#include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" static char *line = NULL; size_t linesize = 0; static struct utimbuf contenttime; static time_t comparetime; static unsigned long totalnew = 0; static struct feed **feeds = NULL; /* normalize path names, transform to lower-case and replace non-alpha and * non-digit with '-' */ static size_t normalizepath(const char *path, char *buf, size_t bufsiz) { size_t i = 0, r = 0; for(; *path && i < bufsiz; path++) { if(isalpha((int)*path) || isdigit((int)*path)) { buf[i++] = tolower((int)*path); r = 0; } else { /* don't repeat '-' */ if(!r) buf[i++] = '-'; r++; } } /* remove trailing '-' */ for(; i > 0 && (buf[i - 1] == '-'); i--) ; if(bufsiz > 0) buf[i] = '\0'; return i; } static void printfeed(FILE *fpitems, FILE *fpin, struct feed *f) { char dirpath[PATH_MAX], filepath[PATH_MAX]; char *fields[FieldLast], *feedname; char name[PATH_MAX]; size_t namelen; struct stat st; FILE *fpcontent = NULL; unsigned int isnew; time_t parsedtime; int r; if(f->name[0]) feedname = f->name; else feedname = "unnamed"; /* make directory for feedname */ if(!(namelen = normalizepath(feedname, name, sizeof(name)))) return; if(strlcpy(dirpath, name, sizeof(dirpath)) >= sizeof(dirpath)) errx(1, "strlcpy: path truncation"); /* directory doesn't exist: try to create it. */ if(stat(dirpath, &st) == -1 && mkdir(dirpath, S_IRWXU) == -1) err(1, "mkdir: %s", dirpath); /* menu if not unnamed */ if(f->name[0]) { fputs("

name, fpitems); fputs("\">name, fpitems); fputs("\">", fpitems); printxmlencoded(f->name, fpitems); fputs("

\n", fpitems); } fputs("\n", fpitems); while(parseline(&line, &linesize, fields, FieldLast, '\t', fpin) > 0) { /* write content */ if(!(namelen = normalizepath(fields[FieldTitle], name, sizeof(name)))) continue; r = snprintf(filepath, sizeof(filepath), "%s/%s.html", dirpath, name); if(r == -1 || (size_t)r >= sizeof(filepath)) errx(1, "snprintf: path truncation"); /* file doesn't exist yet and has write access */ if(access(filepath, F_OK) != 0) { if(!(fpcontent = fopen(filepath, "w+b"))) err(1, "fopen: %s", filepath); fputs("" "\n" "
" "

", fpcontent); printxmlencoded(fields[FieldTitle], fpcontent); fputs("

", fpcontent); printcontent(fields[FieldContent], fpcontent); fputs("
", fpcontent); fclose(fpcontent); } /* set modified and access time of file to time of item. */ r = strtotime(fields[FieldUnixTimestamp], &parsedtime); if(r != -1) { contenttime.actime = parsedtime; contenttime.modtime = parsedtime; utime(filepath, &contenttime); } isnew = (r != -1 && parsedtime >= comparetime) ? 1 : 0; totalnew += isnew; f->totalnew += isnew; f->total++; if(isnew) fputs("", fpitems); else fputs("", fpitems); fputs("\n", fpitems); } fputs("
", fpitems); fputs(fields[FieldTimeFormatted], fpitems); fputs("", fpitems); if(isnew) fputs("", fpitems); fputs("", fpitems); printxmlencoded(fields[FieldTitle], fpitems); fputs("", fpitems); if(isnew) fputs("", fpitems); fputs("
\n", fpitems); } int main(int argc, char *argv[]) { FILE *fpindex, *fpitems, *fpmenu, *fp; int showsidebar = (argc > 1); int i; struct feed *f; if(!(feeds = calloc(argc, sizeof(struct feed *)))) err(1, "calloc"); /* 1 day is old news */ comparetime = time(NULL) - 86400; /* write main index page */ if(!(fpindex = fopen("index.html", "w+b"))) err(1, "fopen: index.html"); if(!(fpmenu = fopen("menu.html", "w+b"))) err(1, "fopen: menu.html"); if(!(fpitems = fopen("items.html", "w+b"))) err(1, "fopen: items.html"); fputs("" "" "
", fpitems); if(argc == 1) { if(!(feeds[0] = calloc(1, sizeof(struct feed)))) err(1, "calloc"); feeds[0]->name = ""; printfeed(fpitems, stdin, feeds[0]); } else { for(i = 1; i < argc; i++) { if(!(feeds[i - 1] = calloc(1, sizeof(struct feed)))) err(1, "calloc"); feeds[i - 1]->name = xbasename(argv[i]); if(!(fp = fopen(argv[i], "r"))) err(1, "fopen: %s", argv[i]); printfeed(fpitems, fp, feeds[i - 1]); if(ferror(fp)) err(1, "ferror: %s", argv[i]); fclose(fp); } } fputs("\n
\n", fpitems); /* div items */ if(showsidebar) { fputs("" "\n" "\n" "", fpmenu); } fputs("\n\tNewsfeed (", fpindex); fprintf(fpindex, "%lu", totalnew); fputs(")\n\t\n" "\n" "\n", fpindex); if(showsidebar) { fputs("\n" " \n", fpindex); } else { fputs("\n", fpindex); } fputs("\t\n" "\t\t\n" "\t\t\n" "\t\n" "\n" "", fpindex); fclose(fpitems); fclose(fpmenu); fclose(fpindex); return 0; }