You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.1 KiB
144 lines
3.1 KiB
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <time.h> |
|
|
|
#include "parse.h" |
|
#include "save.h" |
|
#include "xml.h" |
|
#ifndef OpenBSD |
|
#include "strlcpy.h" |
|
#endif |
|
|
|
#define istag(name) strcmp(x->tag, name) == 0 |
|
|
|
int isatom = 0; |
|
int isitem = 0; |
|
char feedtitle[256]; |
|
struct rss_item item; |
|
|
|
static void xmlattr(XMLParser *, const char *, size_t, const char *, size_t, |
|
const char *, size_t); |
|
static void xmldata(XMLParser *, const char *, size_t); |
|
static void xmldataentity(XMLParser *, const char *, size_t); |
|
static void xmltagend(XMLParser *, const char *, size_t, int); |
|
static void xmltagstart(XMLParser *, const char *, size_t); |
|
static void rfc822_date(char *); |
|
|
|
void |
|
xmlattr(XMLParser *x, const char *t, size_t tl, const char *a, size_t al, |
|
const char *v, size_t vl) |
|
{ |
|
if (!isatom || !(istag("link"))) |
|
return; |
|
|
|
if (strcmp(x->name, "href") == 0) |
|
strlcpy(item.link, x->data, sizeof(item.link)); |
|
} |
|
|
|
static void |
|
xmldata(XMLParser *x, const char *d, size_t dl) |
|
{ |
|
if (isitem == 0) { |
|
if (istag("title")) |
|
strlcpy(feedtitle, d, sizeof(feedtitle)); |
|
return; |
|
} |
|
|
|
if (istag("title")) |
|
strlcpy(item.title, d, sizeof(item.title)); |
|
else if (!isatom && istag("link")) |
|
strlcpy(item.link, d, sizeof(item.link)); |
|
else if (istag("pubDate") || istag("updated") || istag("dc:date")) |
|
strlcpy(item.date, d, sizeof(item.date)); |
|
else if (istag("summary") || istag("content") || istag("description")) |
|
fputs(d, item.desc); |
|
} |
|
|
|
static void |
|
xmldataentity(XMLParser *x, const char *d, size_t dl) |
|
{ |
|
char buf[16]; |
|
int len; |
|
|
|
/* |
|
* try to translate entity, else just pass as data to xmldata |
|
* handler. |
|
*/ |
|
if ((len = xml_entitytostr(d, buf, sizeof(buf))) > 0) |
|
xmldata(x, buf, (size_t) len); |
|
else |
|
xmldata(x, d, dl); |
|
} |
|
|
|
static void |
|
xmltagend(XMLParser *x, const char *t, size_t tl, int isshort) |
|
{ |
|
if (isitem == 0) |
|
return; |
|
|
|
if (istag("item") || istag("entry")) { |
|
isitem = 0; |
|
|
|
fseek(item.desc, 0, SEEK_SET); |
|
rfc822_date(item.date); |
|
|
|
save_item(item, feedtitle); |
|
|
|
fclose(item.desc); |
|
item.desc = NULL; |
|
memset(&item, 0, sizeof(struct rss_item)); |
|
} |
|
} |
|
|
|
static void |
|
xmltagstart(XMLParser *x, const char *t, size_t tl) |
|
{ |
|
if (istag("feed")) { |
|
isatom = 1; |
|
return; |
|
} |
|
|
|
if (istag("item") || istag("entry")) { |
|
isitem = 1; |
|
snprintf(item.descfn, sizeof(item.descfn), "tmp/desc.%6x", rand()); |
|
item.desc = fopen(item.descfn, "w+"); |
|
} |
|
} |
|
|
|
static void |
|
rfc822_date(char *date) |
|
{ |
|
struct tm time; |
|
|
|
memset(&time, 0, sizeof(struct tm)); |
|
|
|
if (strptime(date, "%a, %d %b %Y %T %z", &time) || |
|
strptime(date, "%a, %d %b %Y %T %Z", &time) || |
|
strptime(date, "%a, %d %b %Y %T", &time) || |
|
strptime(date, "%Y-%m-%dT%TZ", &time) || |
|
strptime(date, "%Y-%m-%d", &time)) { |
|
item.epochsec = mktime(&time); |
|
strftime(date, sizeof(item.date), "%a, %d %b %Y %T %z", &time); |
|
} else |
|
fprintf(stderr, "strptime failed when converting pubdate to epoch\n"); |
|
} |
|
|
|
int |
|
parse_item(void) |
|
{ |
|
XMLParser x = {0}; |
|
|
|
x.xmlattr = xmlattr; |
|
x.xmldata = xmldata; |
|
x.xmldataentity = xmldataentity; |
|
x.xmlcdata = xmldata; |
|
x.xmltagend = xmltagend; |
|
x.xmltagstart = xmltagstart; |
|
|
|
x.getnext = getchar; |
|
|
|
xml_parse(&x); |
|
|
|
return 0; |
|
}
|
|
|