sfeed

simple feed reader - forked from git.codemadness.org/sfeed
git clone git://src.gearsix.net/sfeed
Log | Files | Refs | Atom | README | LICENSE

commit 1b4ca40c918664752bde2fa6d06f76a7585a4ecd
parent 8be71604cc18a82e38a2102a200fa8c97d89438c
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Mon, 20 May 2013 19:22:19 +0200

update sfeed_frames and documentation

Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>

Diffstat:
Asfeed_frames.1 | 29+++++++++++++++++++++++++++++
Msfeed_frames.c | 197+++++++++++++++++++++++++++++++++----------------------------------------------
2 files changed, 110 insertions(+), 116 deletions(-)

diff --git a/sfeed_frames.1 b/sfeed_frames.1 @@ -0,0 +1,29 @@ +.TH SFEED 1 sfeed\-VERSION +.SH NAME +sfeed_frames \- format feeds file (TSV) from sfeed_update to HTML with frames +.SH SYNOPSIS +.B sfeed_frames +.RB [path] +.SH OPTIONS +.TP +.B [path] +path to write files to, default is feeds. On success path will contain the +files: index.html which is the main HTML file which contains the frames, +items.html which contains all the items as HTML links to the content, +menu.html which contains links of all the feednames as id to items.html so +you can jump to those items. +.SH STRUCTURE +directory for each feed category in the format: path/feedname/itemname.html +feedname and item names are normalized, whitespace characters are replaced +with a \-, multiple whitespace is replaced by a single \- and trailing +whitespace is ignored. +.SH DESCRIPTION +Format feeds file (TSV) from sfeed_update to HTML. Reads TSV data from +stdin and writes HTML to the specified directory. For the exact TSV format +see sfeed_update(1). +.SH SEE ALSO +.BR sfeed_plain(1) +.BR sfeed_update(1) +.BR sfeed(1) +.SH BUGS +Please report them! diff --git a/sfeed_frames.c b/sfeed_frames.c @@ -3,57 +3,27 @@ #include <stdlib.h> #include <time.h> #include <ctype.h> - #include <unistd.h> - #include <sys/types.h> #include <sys/stat.h> - #include <utime.h> - -#include "common.c" - -/* Feed info. */ -struct feed { - char *name; /* feed name */ - unsigned long new; /* amount of new items per feed */ - unsigned long total; /* total items */ - struct feed *next; /* linked list */ -}; +#include "common.h" +#include "compat.h" static int showsidebar = 1; /* show sidebar ? */ void /* print error message to stderr */ die(const char *s) { - fputs("sfeed_html: ", stderr); + fputs("sfeed_frames: ", stderr); fputs(s, stderr); fputc('\n', stderr); exit(EXIT_FAILURE); } -struct feed * -feednew(void) { - struct feed *f; - if(!(f = calloc(1, sizeof(struct feed)))) - die("can't allocate enough memory"); - return f; -} - -void -feedsfree(struct feed *f) { - struct feed *next; - while(f) { - next = f->next; - free(f->name); - free(f); - f = next; - } -} - /* print text, ignore tabs, newline and carriage return etc * print some HTML 2.0 / XML 1.0 as normal text */ void -print_content_test(const char *s, FILE *fp) { +printcontent(const char *s, FILE *fp) { const char *p; int len = 0; for(p = s; *p; p++) { @@ -72,31 +42,10 @@ print_content_test(const char *s, FILE *fp) { } } -/* print feed name for id; spaces and tabs in string as "-" (spaces in anchors are not valid). */ -void -printfeednameid(const char *s, FILE *fp) { - for(; *s; s++) - fputc(isspace((int)*s) ? '-' : *s, fp); -} - -void -printhtmlencoded(const char *s, FILE *fp) { - for(; *s; s++) { - switch(*s) { - case '<': fputs("&lt;", fp); break; - case '>': fputs("&gt;", fp); break; -/* case '&': fputs("&amp;", fp); break;*/ - default: - fputc(*s, fp); - } - } -} - -void +size_t makepathname(char *buffer, size_t bufsiz, const char *path) { const char *p = path; size_t i = 0, r = 0; - /*for(p = path; isspace((int)*p); p++);*/ /* remove leading whitespace */ for(; *p && i < bufsiz; p++) { if(isalpha((int)*p) || isdigit((int)*p)) { buffer[i++] = tolower((int)*p); @@ -112,6 +61,7 @@ makepathname(char *buffer, size_t bufsiz, const char *path) { /* remove trailing - */ for(; i > 0 && (buffer[i] == '-' || buffer[i] == '\0'); i--) buffer[i] = '\0'; + return i; } int @@ -123,78 +73,84 @@ int main(int argc, char **argv) { char *line = NULL, *fields[FieldLast]; unsigned long totalfeeds = 0, totalnew = 0; - unsigned int islink, isnew; + unsigned int isnew; struct feed *feedcurrent = NULL, *feeds = NULL; /* start of feeds linked-list. */ time_t parsedtime, comparetime; size_t size = 0; char name[256]; - char dirpath[256]; + char dirpath[1024]; char filepath[1024]; char reldirpath[1024]; char relfilepath[1024]; FILE *fpindex, *fpitems, *fpmenu, *fpcontent; - char feedname[1024]; char *basepath = "feeds"; - struct utimbuf contenttime = { 0 }; + struct utimbuf contenttime; + size_t namelen = 0; - /* TODO: write menu to file */ - /* TODO: write items to file */ - /* TODO: write items per category to file? */ + memset(&contenttime, 0, sizeof(contenttime)); if(argc > 1 && argv[1][0] != '\0') basepath = argv[1]; -/* tzset();*/ comparetime = time(NULL) - (3600 * 24); /* 1 day is old news */ - - mkdir(basepath, S_IRWXU); + xmkdir(basepath, S_IRWXU); /* write main index page */ - snprintf(dirpath, sizeof(dirpath) - 1, "%s/index.html", basepath); + if(strlen(basepath) + strlen("/index.html") < sizeof(dirpath) - 1) + sprintf(dirpath, "%s/index.html", basepath); if((fpindex = fopen(dirpath, "w+b"))) { } - snprintf(dirpath, sizeof(dirpath) - 1, "%s/menu.html", basepath); + if(strlen(basepath) + strlen("/menu.html") < sizeof(dirpath) - 1) + sprintf(dirpath, "%s/menu.html", basepath); if(!(fpmenu = fopen(dirpath, "w+b"))) { /* TODO: error */ fclose(fpindex); return EXIT_FAILURE; } - snprintf(dirpath, sizeof(dirpath) - 1, "%s/items.html", basepath); + if(strlen(basepath) + strlen("/items.html") < sizeof(dirpath) - 1) + sprintf(dirpath, "%s/items.html", basepath); if(!(fpitems = fopen(dirpath, "w+b"))) { /* TODO: error */ fclose(fpmenu); fclose(fpindex); return EXIT_FAILURE; } + fclose(fpcontent); + fputs("<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" /></head>", fpitems); + fputs("<body class=\"frame\"><div id=\"items\">", fpitems); - feedname[0] = '\0'; - while(parseline(&line, &size, fields, FieldLast, stdin, FieldSeparator) > 0) { + while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { dirpath[0] = '\0'; filepath[0] = '\0'; reldirpath[0] = '\0'; relfilepath[0] = '\0'; - makepathname(name, sizeof(name) - 1, fields[FieldFeedName]); - if(name[0] != '\0') { - snprintf(dirpath, sizeof(dirpath) - 1, "%s/%s", basepath, name); + namelen = makepathname(name, sizeof(name) - 1, fields[FieldFeedName]); + if(namelen) { + if(strlen(basepath) + namelen + 1 < sizeof(dirpath) - 1) + sprintf(dirpath, "%s/%s", basepath, name); /* TODO: handle error. */ - if(mkdir(dirpath, S_IRWXU) != -1) { + if(xmkdir(dirpath, S_IRWXU) != -1) { } -/* snprintf(reldirpath, sizeof(reldirpath) - 1, "%s", name);*/ strncpy(reldirpath, name, sizeof(reldirpath) - 1); - makepathname(name, sizeof(name), fields[FieldTitle]); - if(name[0] != '\0') { - snprintf(filepath, sizeof(filepath) - 1, "%s/%s.html", dirpath, name); - snprintf(relfilepath, sizeof(relfilepath) - 1, "%s/%s.html", reldirpath, name); - - /* TODO: if file exists, dont overwrite. */ - /* TODO: give file title and timestamp of article, touch() ?. */ + namelen = makepathname(name, sizeof(name), fields[FieldTitle]); + if(namelen) { + if(strlen(dirpath) + namelen + strlen("/.html") < sizeof(filepath) - 1) + sprintf(filepath, "%s/%s.html", dirpath, name); + if(strlen(reldirpath) + namelen + strlen("/.html") < sizeof(relfilepath) - 1) + sprintf(relfilepath, "%s/%s.html", reldirpath, name); if(!fileexists(filepath) && (fpcontent = fopen(filepath, "w+b"))) { - fputs("<html><body>", fpcontent); - fputs("<h2>", fpcontent); + fputs("<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"../../style.css\" /></head>", fpcontent); + fputs("<body class=\"frame\"><div class=\"content\">", fpcontent); + fputs("<h2><a href=\"", fpcontent); + if(fields[FieldBaseSiteUrl][0] != '\0') + printlink(fields[FieldLink], fields[FieldBaseSiteUrl], fpcontent); + else + printlink(fields[FieldLink], fields[FieldFeedUrl], fpcontent); + fputs("\">", fpcontent); printhtmlencoded(fields[FieldTitle], fpcontent); - fputs("</h2>", fpcontent); - print_content_test(fields[FieldContent], fpcontent); - fputs("</body></html>", fpcontent); + fputs("</a></h2>", fpcontent); + printcontent(fields[FieldContent], fpcontent); + fputs("</div></body></html>", fpcontent); fclose(fpcontent); } @@ -210,7 +166,6 @@ main(int argc, char **argv) { die("can't allocate enough memory"); feeds = feedcurrent; /* first item. */ if(fields[FieldFeedName][0] == '\0') { - fputs("-nosidebar", fpitems); /* set other id on div if no sidebar for styling */ showsidebar = 0; } } @@ -226,7 +181,7 @@ main(int argc, char **argv) { fputs(feedcurrent->name, fpitems); fputs("</a></h2>\n", fpitems); } - fputs("<table>", fpitems); + fputs("<table cellpadding=\"0\" cellspacing=\"0\">\n", fpitems); totalfeeds++; } /* write item. */ @@ -237,15 +192,16 @@ main(int argc, char **argv) { utime(filepath, &contenttime); isnew = (parsedtime >= comparetime); - islink = (strlen(fields[FieldLink]) > 0); totalnew += isnew; - feedcurrent->new += isnew; + feedcurrent->totalnew += isnew; feedcurrent->total++; - + if(isnew) + fputs("<tr class=\"n\"><td nowrap valign=\"top\">", fpitems); + else + fputs("<tr><td nowrap valign=\"top\">", fpitems); fputs("<tr><td nowrap valign=\"top\">", fpitems); fputs(fields[FieldTimeFormatted], fpitems); - fputs("</td><td valign=\"top\">", fpitems); - + fputs("</td><td nowrap valign=\"top\">", fpitems); if(isnew) fputs("<b><u>", fpitems); fputs("<a href=\"", fpitems); @@ -261,41 +217,50 @@ main(int argc, char **argv) { } if(totalfeeds) { fputs("</table>\n", fpitems); - fputs("\t\t</div>\n", fpitems); /* div items */ } + fputs("\n</div></body>\n</html>", fpitems); /* div items */ if(showsidebar) { -/* fputs("\t\t<div id=\"sidebar\">\n\t\t\t<ul>\n", fpmenu);*/ + fputs("<html><head>", fpmenu); + fputs("<link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" />", fpmenu); + fputs("</head><body class=\"frame\"><div id=\"sidebar\">", fpmenu); for(feedcurrent = feeds; feedcurrent; feedcurrent = feedcurrent->next) { if(!feedcurrent->name || feedcurrent->name[0] == '\0') continue; - fputs("<a href=\"items.html#", fpmenu); + if(feedcurrent->totalnew) + fputs("<a class=\"n\" href=\"items.html#", fpmenu); + else + fputs("<a href=\"items.html#", fpmenu); printfeednameid(feedcurrent->name, fpmenu); fputs("\" target=\"items\">", fpmenu); - if(feedcurrent->new > 0) + if(feedcurrent->totalnew > 0) fputs("<b><u>", fpmenu); fputs(feedcurrent->name, fpmenu); - fprintf(fpmenu, " (%lu)", feedcurrent->new); - if(feedcurrent->new > 0) + fprintf(fpmenu, " (%lu)", feedcurrent->totalnew); + if(feedcurrent->totalnew > 0) fputs("</u></b>", fpmenu); fputs("</a><br/>\n", fpmenu); } -/* fputs("\t\t\t</ul>\n\t\t</div>\n", fpmenu);*/ + fputs("</div></body></html>", fpmenu); } - fputs("<!DOCTYPE html>" - "<html>" - " <head>" - " <title>Newsfeeds (", fpindex); - fprintf(fpindex, "%lu", totalnew); - fputs(")</title>" - " </head>" - " <frameset framespacing=\"0\" cols=\"200,*\" frameborder=\"1\">" - " <frame name=\"menu\" src=\"menu.html\" target=\"menu\">" - " <frameset id=\"frameset\" framespacing=\"0\" cols=\"50%,50%\" frameborder=\"1\">" - " <frame name=\"items\" src=\"items.html\" target=\"items\">" - " <frame name=\"content\" target=\"content\">" - " </frameset>" - " </frameset>" + fputs("<!DOCTYPE html><html><head>\n", fpindex); + fprintf(fpindex, "\t<title>Newsfeed (%lu)</title>\n", totalnew); + fputs("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" />\n", fpindex); + fputs("</head>\n", fpindex); + if(showsidebar) { + fputs( + "<frameset framespacing=\"0\" cols=\"200,*\" frameborder=\"1\">" + " <frame name=\"menu\" src=\"menu.html\" target=\"menu\">", fpindex); + } else { + fputs( + "<frameset framespacing=\"0\" cols=\"*\" frameborder=\"1\">", fpindex); + } + fputs( + " <frameset id=\"frameset\" framespacing=\"0\" cols=\"50%,50%\" frameborder=\"1\">" + " <frame name=\"items\" src=\"items.html\" target=\"items\">" + " <frame name=\"content\" target=\"content\">" + " </frameset>" + "</frameset>" "</html>", fpindex); fclose(fpmenu);