sfeed

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

sfeed_gopher.c (4450B)


      1 #include <sys/types.h>
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <time.h>
      7 
      8 #include "util.h"
      9 
     10 static struct feed f;
     11 static char *prefixpath = "/", *host = "127.0.0.1", *port = "70"; /* default */
     12 static char *line;
     13 static size_t linesize;
     14 static time_t comparetime;
     15 
     16 /* Escape characters in gopher, CR and LF are ignored */
     17 void
     18 gophertext(FILE *fp, const char *s)
     19 {
     20 	for (; *s; s++) {
     21 		switch (*s) {
     22 		case '\r': /* ignore CR */
     23 		case '\n': /* ignore LF */
     24 			break;
     25 		case '\t':
     26 			fputs("        ", fp);
     27 			break;
     28 		default:
     29 			putc(*s, fp);
     30 			break;
     31 		}
     32 	}
     33 }
     34 
     35 static void
     36 printfeed(FILE *fpitems, FILE *fpin, struct feed *f)
     37 {
     38 	struct uri u;
     39 	char *fields[FieldLast];
     40 	char *itemhost, *itemport, *itempath, *itemquery, *itemfragment;
     41 	ssize_t linelen;
     42 	unsigned int isnew;
     43 	struct tm rtm, *tm;
     44 	time_t parsedtime;
     45 	int itemtype;
     46 
     47 	if (f->name[0]) {
     48 		fprintf(fpitems, "i%s\t\t%s\t%s\r\n", f->name, host, port);
     49 		fprintf(fpitems, "i\t\t%s\t%s\r\n", host, port);
     50 	}
     51 
     52 	while ((linelen = getline(&line, &linesize, fpin)) > 0 &&
     53 	       !ferror(fpitems)) {
     54 		if (line[linelen - 1] == '\n')
     55 			line[--linelen] = '\0';
     56 		parseline(line, fields);
     57 
     58 		itemhost = host;
     59 		itemport = port;
     60 		itemtype = 'i';
     61 		itempath = fields[FieldLink];
     62 		itemquery = "";
     63 		itemfragment = "";
     64 
     65 		if (fields[FieldLink][0]) {
     66 			itemtype = 'h';
     67 			/* if it's a gopher URL then change it into a DirEntity */
     68 			if (!strncmp(fields[FieldLink], "gopher://", 9) &&
     69 			    uri_parse(fields[FieldLink], &u) != -1) {
     70 				itemhost = u.host;
     71 				itemport = u.port[0] ? u.port : "70";
     72 				itemtype = '1';
     73 				itempath = u.path;
     74 				itemquery = u.query;
     75 				itemfragment = u.fragment;
     76 
     77 				if (itempath[0] == '/') {
     78 					itempath++;
     79 					if (*itempath) {
     80 						itemtype = *itempath;
     81 						itempath++;
     82 					}
     83 				}
     84 			}
     85 		}
     86 
     87 		parsedtime = 0;
     88 		if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) &&
     89 		    (tm = localtime_r(&parsedtime, &rtm))) {
     90 			isnew = (parsedtime >= comparetime) ? 1 : 0;
     91 			f->totalnew += isnew;
     92 
     93 			fprintf(fpitems, "%c%c %04d-%02d-%02d %02d:%02d ",
     94 			        itemtype,
     95 			        isnew ? 'N' : ' ',
     96 			        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
     97 			        tm->tm_hour, tm->tm_min);
     98 		} else {
     99 			fprintf(fpitems, "%c                   ", itemtype);
    100 		}
    101 		f->total++;
    102 
    103 		gophertext(fpitems, fields[FieldTitle]);
    104 		fputs("\t", fpitems);
    105 		if (itemtype == 'h' && fields[FieldLink] == itempath)
    106 			fputs("URL:", fpitems);
    107 		gophertext(fpitems, itempath);
    108 		if (itemquery[0]) {
    109 			fputs("?", fpitems);
    110 			gophertext(fpitems, itemquery);
    111 		}
    112 		if (itemfragment[0]) {
    113 			fputs("#", fpitems);
    114 			gophertext(fpitems, itemfragment);
    115 		}
    116 		fprintf(fpitems, "\t%s\t%s\r\n", itemhost, itemport);
    117 	}
    118 	fputs(".\r\n", fpitems);
    119 }
    120 
    121 int
    122 main(int argc, char *argv[])
    123 {
    124 	FILE *fpitems, *fpindex, *fp;
    125 	char *name, *p;
    126 	int i;
    127 
    128 	if (argc == 1) {
    129 		if (pledge("stdio", NULL) == -1)
    130 			err(1, "pledge");
    131 	} else {
    132 		if (unveil("/", "r") == -1)
    133 			err(1, "unveil: /");
    134 		if (unveil(".", "rwc") == -1)
    135 			err(1, "unveil: .");
    136 		if (pledge("stdio rpath wpath cpath", NULL) == -1)
    137 			err(1, "pledge");
    138 	}
    139 
    140 	if ((comparetime = time(NULL)) == (time_t)-1)
    141 		errx(1, "time");
    142 	/* 1 day is old news */
    143 	comparetime -= 86400;
    144 
    145 	if ((p = getenv("SFEED_GOPHER_HOST")))
    146 		host = p;
    147 	if ((p = getenv("SFEED_GOPHER_PORT")))
    148 		port = p;
    149 
    150 	if (argc == 1) {
    151 		f.name = "";
    152 		printfeed(stdout, stdin, &f);
    153 		checkfileerror(stdin, "<stdin>", 'r');
    154 		checkfileerror(stdout, "<stdout>", 'w');
    155 	} else {
    156 		if ((p = getenv("SFEED_GOPHER_PATH")))
    157 			prefixpath = p;
    158 
    159 		/* write main index page */
    160 		if (!(fpindex = fopen("index", "wb")))
    161 			err(1, "fopen: index");
    162 
    163 		for (i = 1; i < argc; i++) {
    164 			memset(&f, 0, sizeof(f));
    165 			name = ((name = strrchr(argv[i], '/'))) ? name + 1 : argv[i];
    166 			f.name = name;
    167 
    168 			if (!(fp = fopen(argv[i], "r")))
    169 				err(1, "fopen: %s", argv[i]);
    170 			if (!(fpitems = fopen(name, "wb")))
    171 				err(1, "fopen");
    172 			printfeed(fpitems, fp, &f);
    173 			checkfileerror(fp, argv[i], 'r');
    174 			checkfileerror(fpitems, name, 'w');
    175 			fclose(fp);
    176 			fclose(fpitems);
    177 
    178 			/* append directory item to index */
    179 			fputs("1", fpindex);
    180 			gophertext(fpindex, name);
    181 			fprintf(fpindex, " (%lu/%lu)\t", f.totalnew, f.total);
    182 			gophertext(fpindex, prefixpath);
    183 			gophertext(fpindex, name);
    184 			fprintf(fpindex, "\t%s\t%s\r\n", host, port);
    185 		}
    186 		fputs(".\r\n", fpindex);
    187 		checkfileerror(fpindex, "index", 'w');
    188 		fclose(fpindex);
    189 	}
    190 
    191 	return 0;
    192 }