summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sfeed_frames.129
-rw-r--r--sfeed_frames.c197
2 files changed, 110 insertions, 116 deletions
diff --git a/sfeed_frames.1 b/sfeed_frames.1
new file mode 100644
index 0000000..0f6d00e
--- /dev/null
+++ 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
index 54464c3..6152909 100644
--- 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);