sfeed

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

sfeed_gopher.c (raw) (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 }