ref: 12526901e2bd1b7eb76d029a3f7ef8878de16f4d
parent: 8fdbac99c8c167acc77ca43661a50e9360c905f8
author: sirjofri <sirjofri@sirjofri.de>
date: Tue Jun 9 05:55:13 EDT 2020
adds atom support (including date)
--- /dev/null
+++ b/date.c
@@ -1,0 +1,201 @@
+#include <u.h>
+#include <libc.h>
+#include "date.h"
+
+int
+str2mon(char *s)
+{
+ if(!strcmp(s, "Jan")) return 0;
+ if(!strcmp(s, "Feb")) return 1;
+ if(!strcmp(s, "Mar")) return 2;
+ if(!strcmp(s, "Apr")) return 3;
+ if(!strcmp(s, "May")) return 4;
+ if(!strcmp(s, "Jun")) return 5;
+ if(!strcmp(s, "Jul")) return 6;
+ if(!strcmp(s, "Aug")) return 7;
+ if(!strcmp(s, "Sep")) return 8;
+ if(!strcmp(s, "Oct")) return 9;
+ if(!strcmp(s, "Nov")) return 10;
+ if(!strcmp(s, "Dec")) return 11;
+ return 0;
+}
+
+int
+str2wday(char *s)
+{
+ if(!strcmp(s, "Sun")) return 0;
+ if(!strcmp(s, "Mon")) return 1;
+ if(!strcmp(s, "Tue")) return 2;
+ if(!strcmp(s, "Wed")) return 3;
+ if(!strcmp(s, "Thu")) return 4;
+ if(!strcmp(s, "Fri")) return 5;
+ if(!strcmp(s, "Sat")) return 6;
+ return 0;
+}
+
+int
+doty(int day, int month, int year)
+{
+ int n, i;
+
+ n = 0;
+ for(i = 0; i < month; i++){
+ if(i == 0) n += 31;
+ if(i == 1){
+ if(year%4 == 0 && year%100 == 0 && year%400 != 0)
+ n += 29;
+ else
+ n += 28;
+ }
+ if(i == 2) n += 31;
+ if(i == 3) n += 30;
+ if(i == 4) n += 31;
+ if(i == 5) n += 30;
+ if(i == 6) n += 31;
+ if(i == 7) n += 31;
+ if(i == 8) n += 30;
+ if(i == 9) n += 31;
+ if(i == 10) n += 30;
+ if(i == 11) n += 31;
+ }
+
+ n += day;
+
+ return n;
+}
+
+long
+parseatomdate(char *input)
+{
+ /* YYYY-MM-DDTHH:MM:SSZ */
+ /* YYYY year */
+ /* MM month */
+ /* DD day of month */
+ /* T or space */
+ /* HH hour */
+ /* MM minute */
+ /* SS seconds */
+ /* .SS seconds (sub, optional) */
+ /* Z zulu (UTC+0) */
+ /* +HH:MM tz offset */
+
+ /* examples: length */
+ /* 2020-06-05( |T)13:20:35.44+04:00 28 */
+ /* 2020-06-05( |T)13:20:35+04:00 25 */
+ /* 2020-06-05( |T)13:20:35.44Z 23 */
+ /* 2020-06-05( |T)13:20:35Z 20 */
+
+ Tm ret;
+ char *args[9];
+ char s[32];
+ int n;
+
+ strcpy(s, input);
+
+ switch(strlen(s)){
+ case 28:
+ n = getfields(s, args, 9, 1, "- T:.+Z");
+ if(n != 9)
+ sysfatal("error parsing atom date: %d", n);
+ ret.year = atoi(args[0]) - 1900;
+ ret.mon = atoi(args[1]) - 1;
+ ret.mday = atoi(args[2]);
+ ret.tzoff = atoi(args[7]);
+ ret.hour = atoi(args[3]);
+ ret.min = atoi(args[4]);
+ ret.sec = atoi(args[5]);
+ break;
+ case 25:
+ n = getfields(s, args, 8, 1, "- T:.+Z");
+ if(n != 8)
+ sysfatal("error parsing atom date: %d", n);
+ ret.year = atoi(args[0]) - 1900;
+ ret.mon = atoi(args[1]) - 1;
+ ret.mday = atoi(args[2]);
+ ret.tzoff = atoi(args[6]);
+ ret.hour = atoi(args[3]);
+ ret.min = atoi(args[4]);
+ ret.sec = atoi(args[5]);
+ break;
+ case 23:
+ n = getfields(s, args, 7, 1, "- T:.+Z");
+ if(n != 7)
+ sysfatal("error parsing atom date: %d", n);
+ ret.year = atoi(args[0]) - 1900;
+ ret.mon = atoi(args[1]);
+ ret.mday = atoi(args[2]);
+ ret.tzoff = 0;
+ ret.hour = atoi(args[3]);
+ ret.min = atoi(args[4]);
+ ret.sec = atoi(args[5]);
+ break;
+ case 20:
+ n = getfields(s, args, 6, 1, "- T:.+Z");
+ if(n != 6)
+ sysfatal("error parsing atom date: %d", n);
+ ret.year = atoi(args[0]) - 1900;
+ ret.mon = atoi(args[1]) - 1;
+ ret.mday = atoi(args[2]);
+ ret.tzoff = 0;
+ ret.hour = atoi(args[3]);
+ ret.min = atoi(args[4]);
+ ret.sec = atoi(args[5]);
+ break;
+ default:
+ sysfatal("error parsing atom date format: %s", s);
+ }
+ ret.yday = doty(ret.mday, ret.mon, ret.year);
+
+ return tm2sec(&ret) - ret.tzoff*60*60;
+}
+
+long
+parsedate(char *s)
+{
+ Tm ret;
+ char input[64];
+ char *args[8];
+ int n, i;
+
+ strcpy(input, s);
+ n = getfields(input, args, 8, 1, ", :");
+
+ if(n < 8){
+ /* try parsing atom date */
+ return parseatomdate(s);
+ }
+
+ for(i = 0; i < n; i++){
+ if(!args[i])
+ sysfatal("error parsing pubDate: %s", s);
+ switch(i){
+ case 0: /* day of the week */
+ ret.wday = str2wday(args[i]);
+ break;
+ case 1: /* day of the month */
+ ret.mday = atoi(args[i]);
+ break;
+ case 2: /* month of the year */
+ ret.mon = str2mon(args[i]);
+ break;
+ case 3: /* year */
+ ret.year = atoi(args[i]) - 1900;
+ break;
+ case 4: /* hour */
+ ret.hour = atoi(args[i]);
+ break;
+ case 5: /* minute */
+ ret.min = atoi(args[i]);
+ break;
+ case 6: /* second */
+ ret.sec = atoi(args[i]);
+ break;
+ case 7: /* timezone offset */
+ ret.tzoff = atoi(args[i])/100;
+ break;
+ }
+ }
+ ret.yday = doty(ret.mday, ret.mon, ret.year);
+
+ return tm2sec(&ret) - ret.tzoff*60*60;
+}
\ No newline at end of file
--- a/date.h
+++ b/date.h
@@ -1,116 +1,5 @@
-int
-str2mon(char *s)
-{
- if(!strcmp(s, "Jan")) return 0;
- if(!strcmp(s, "Feb")) return 1;
- if(!strcmp(s, "Mar")) return 2;
- if(!strcmp(s, "Apr")) return 3;
- if(!strcmp(s, "May")) return 4;
- if(!strcmp(s, "Jun")) return 5;
- if(!strcmp(s, "Jul")) return 6;
- if(!strcmp(s, "Aug")) return 7;
- if(!strcmp(s, "Sep")) return 8;
- if(!strcmp(s, "Oct")) return 9;
- if(!strcmp(s, "Nov")) return 10;
- if(!strcmp(s, "Dec")) return 11;
- return 0;
-}
-
-int
-str2wday(char *s)
-{
- if(!strcmp(s, "Sun")) return 0;
- if(!strcmp(s, "Mon")) return 1;
- if(!strcmp(s, "Tue")) return 2;
- if(!strcmp(s, "Wed")) return 3;
- if(!strcmp(s, "Thu")) return 4;
- if(!strcmp(s, "Fri")) return 5;
- if(!strcmp(s, "Sat")) return 6;
- return 0;
-}
-
-int
-doty(int day, int month, int year)
-{
- int n, i;
-
- n = 0;
- for(i = 0; i < month; i++){
- if(i == 0) n += 31;
- if(i == 1){
- if(year%4 == 0 && year%100 == 0 && year%400 != 0)
- n += 29;
- else
- n += 28;
- }
- if(i == 2) n += 31;
- if(i == 3) n += 30;
- if(i == 4) n += 31;
- if(i == 5) n += 30;
- if(i == 6) n += 31;
- if(i == 7) n += 31;
- if(i == 8) n += 30;
- if(i == 9) n += 31;
- if(i == 10) n += 30;
- if(i == 11) n += 31;
- }
-
- n += day;
-
- return n;
-}
-
-long
-parsedate(char *s)
-{
- Tm ret;
- char input[64];
- char *args[8];
- int n, i;
-
- strcpy(input, s);
- n = getfields(input, args, 8, 1, ", :");
-
- if(n < 8)
- sysfatal("error parsing pubDate: %s", s);
-
- for(i = 0; i < n; i++){
- if(!args[i])
- sysfatal("error parsing pubDate: %s", s);
- switch(i){
- case 0: /* day of the week */
- ret.wday = str2wday(args[i]);
- break;
- case 1: /* day of the month */
- ret.mday = atoi(args[i]);
- break;
- case 2: /* month of the year */
- ret.mon = str2mon(args[i]);
- break;
- case 3: /* year */
- ret.year = atoi(args[i]) - 1900;
- break;
- case 4: /* hour */
- ret.hour = atoi(args[i]);
- break;
- case 5: /* minute */
- ret.min = atoi(args[i]);
- break;
- case 6: /* second */
- ret.sec = atoi(args[i]);
- break;
- case 7: /* timezone offset */
- ret.tzoff = atoi(args[i])/100;
- break;
- }
- }
- /*
- ret.zone[0] = 'C';
- ret.zone[1] = 'E';
- ret.zone[2] = 'S';
- ret.zone[3] = 'T';
- */
- ret.yday = doty(ret.mday, ret.mon, ret.year);
-
- return tm2sec(&ret) - ret.tzoff*60*60;
-}
\ No newline at end of file
+int str2mon(char *s);
+int str2wday(char *s);
+int doty(int day, int month, int year);
+long parseatomdate(char *s);
+long parsedate(char *s);
--- a/fetchnews.rc
+++ b/fetchnews.rc
@@ -2,8 +2,8 @@
O=6
-urls=( https://www.tagesschau.de/xml/rss2 https://lukesmith.xyz/rss.xml )
-prefixes=( tschau lukesmith )
+urls=( https://www.tagesschau.de/xml/rss2 https://lukesmith.xyz/rss.xml https://www.heise.de/security/rss/news-atom.xml )
+prefixes=( tschau lukesmith heisesec )
ramfs -m /lib/news
--- a/mkfile
+++ b/mkfile
@@ -1,7 +1,7 @@
</$objtype/mkfile
TARG=rssfill
-OFILES=rssfill.$O
+OFILES=rssfill.$O date.$O
HFILES=rssfill.h xmlpull.h date.h
</sys/src/cmd/mkone
--- a/rssfill.c
+++ b/rssfill.c
@@ -246,6 +246,10 @@
st = DATE;
break;
}
+ if(!strcmp(x->na, "updated") && st == ITEM){
+ st = DATE;
+ break;
+ }
break;
case START_END_TAG:
break;
@@ -297,6 +301,10 @@
break;
}
if(!strcmp(x->na, "pubDate") && st == DATE){
+ st = ITEM;
+ break;
+ }
+ if(!strcmp(x->na, "updated") && st == DATE){
st = ITEM;
break;
}