summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sfeed.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/sfeed.c b/sfeed.c
index b308188..560e808 100644
--- a/sfeed.c
+++ b/sfeed.c
@@ -54,6 +54,7 @@ enum TagId {
AtomTagMediaDescription, AtomTagSummary, AtomTagContent,
AtomTagId,
AtomTagLink,
+ AtomTagLinkAlternate,
AtomTagAuthor,
TagLast
};
@@ -141,8 +142,10 @@ static FeedTag atomtags[] = {
{ STRP("updated"), AtomTagUpdated }
};
-/* map tagid type to RSS/Atom field */
+/* map tagid type to RSS/Atom field
+ NOTE: all tags must be defined */
static int fieldmap[TagLast] = {
+ [TagUnknown] = -1,
/* RSS */
[RSSTagDcdate] = FeedFieldTime,
[RSSTagPubdate] = FeedFieldTime,
@@ -162,7 +165,8 @@ static int fieldmap[TagLast] = {
[AtomTagSummary] = FeedFieldContent,
[AtomTagContent] = FeedFieldContent,
[AtomTagId] = FeedFieldId,
- [AtomTagLink] = FeedFieldLink,
+ [AtomTagLink] = -1,
+ [AtomTagLinkAlternate] = FeedFieldLink,
[AtomTagAuthor] = FeedFieldAuthor
};
@@ -172,6 +176,9 @@ static const char *baseurl = "";
static FeedContext ctx;
static XMLParser parser; /* XML parser state */
+static String atomlink;
+static int atomlinktype;
+
/* Unique tagid for parsed tag name. */
static enum TagId
gettag(enum FeedType feedtype, const char *name, size_t namelen)
@@ -619,11 +626,16 @@ xmlattr(XMLParser *p, const char *t, size_t tl, const char *n, size_t nl,
ctx.contenttype = ContentTypeHTML;
}
} else if (ctx.tagid == AtomTagLink &&
- isattr(n, nl, STRP("href")) &&
- ctx.field)
- {
- /* link href attribute */
- string_append(ctx.field, v, vl);
+ isattr(n, nl, STRP("rel"))) {
+ /* empty or "alternate": other types could be
+ "enclosure", "related", "self" or "via" */
+ if (!vl || isattr(v, vl, STRP("alternate")))
+ atomlinktype = AtomTagLinkAlternate;
+ else
+ atomlinktype = 0;
+ } else if (ctx.tagid == AtomTagLink &&
+ isattr(n, nl, STRP("href"))) {
+ string_append(&atomlink, v, vl);
}
}
}
@@ -731,12 +743,19 @@ xmltagstart(XMLParser *p, const char *t, size_t tl)
tagid = gettag(ctx.feedtype, t, tl);
ctx.tagid = tagid;
+ /* without a rel attribute the default link type is "alternate" */
+ if (tagid == AtomTagLink) {
+ atomlinktype = AtomTagLinkAlternate;
+ string_clear(&atomlink); /* reuse and clear temporary link */
+ }
+
/* map tag type to field: unknown or lesser priority is ignored,
when tags of the same type are repeated only the first is used. */
- if (tagid == TagUnknown || tagid <= ctx.fields[fieldmap[tagid]].tagid) {
+ if (fieldmap[tagid] == -1 || tagid <= ctx.fields[fieldmap[tagid]].tagid) {
ctx.field = NULL;
return;
}
+
ctx.iscontenttag = (fieldmap[ctx.tagid] == FeedFieldContent);
ctx.field = &(ctx.fields[fieldmap[ctx.tagid]].str);
ctx.fields[fieldmap[ctx.tagid]].tagid = tagid;
@@ -784,6 +803,14 @@ xmltagend(XMLParser *p, const char *t, size_t tl, int isshort)
}
return;
}
+ } else if (ctx.tagid == AtomTagLink) {
+ /* map tag type to field: unknown or lesser priority is ignored,
+ when tags of the same type are repeated only the first is used. */
+ if (atomlinktype && atomlinktype > ctx.fields[fieldmap[atomlinktype]].tagid) {
+ string_append(&ctx.fields[fieldmap[atomlinktype]].str,
+ atomlink.data, atomlink.len);
+ ctx.fields[fieldmap[atomlinktype]].tagid = atomlinktype;
+ }
} else if (!ctx.tagid && ((ctx.feedtype == FeedTypeAtom &&
istag(t, tl, STRP("entry"))) || /* Atom */
(ctx.feedtype == FeedTypeRSS &&