mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-15 04:39:31 +00:00
[Bug 344389] feed parser doesn't expose guid/atom:id/rdf:about correctly. r=ben
This commit is contained in:
parent
9a79b08c79
commit
3441890217
@ -45,14 +45,14 @@ interface nsIArray;
|
||||
* but they have some divergent attributes and require
|
||||
* different convenience methods.
|
||||
*/
|
||||
[scriptable, uuid(c7e65344-df1f-4a75-9615-d58357c1554b)]
|
||||
[scriptable, uuid(b7e7b6b9-a461-4817-9003-3e6b9005945f)]
|
||||
interface nsIFeedContainer : nsISupports
|
||||
{
|
||||
/**
|
||||
* Many feeds contain an ID distinct from their URI, and
|
||||
* entries have standard fields for this in all major formats.
|
||||
*/
|
||||
attribute AString identifier;
|
||||
attribute AString id;
|
||||
|
||||
/**
|
||||
* The baseURI for the Entry or Feed.
|
||||
|
@ -59,7 +59,12 @@ const XMLNS = "http://www.w3.org/XML/1998/namespace";
|
||||
/***** Some general utils *****/
|
||||
function strToURI(link, base) {
|
||||
var base = base || null;
|
||||
return gIoService.newURI(link, null, base);
|
||||
try {
|
||||
return gIoService.newURI(link, null, base);
|
||||
}
|
||||
catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isArray(a) {
|
||||
@ -178,6 +183,19 @@ function bagHasKey(bag, key) {
|
||||
}
|
||||
}
|
||||
|
||||
function makePropGetter(key) {
|
||||
return function FeedPropGetter(bag) {
|
||||
try {
|
||||
return value = bag.getProperty(key);
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* XXX Thunderbird's W3C-DTF function
|
||||
*
|
||||
@ -325,6 +343,7 @@ function Feed() {
|
||||
this._title = null;
|
||||
this.items = [];
|
||||
this.link = null;
|
||||
this.id = null;
|
||||
this.baseURI = null;
|
||||
}
|
||||
Feed.prototype = {
|
||||
@ -349,6 +368,7 @@ Feed.prototype = {
|
||||
_sub: ["description","dc:description","rss1:description",
|
||||
"atom03:tagline","atom:subtitle"],
|
||||
items: ["items","atom03_entries","entries"],
|
||||
id: ["atom:id","rdf:about"],
|
||||
_title: ["title","rss1:title", "atom03:title","atom:title"],
|
||||
link: [["link",strToURI],["rss1:link",strToURI]],
|
||||
categories: ["categories", "dc:subject"],
|
||||
@ -390,7 +410,7 @@ Feed.prototype = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
QueryInterface: function Feed_QI(iid) {
|
||||
if (iid.equals(Ci.nsIFeed) ||
|
||||
iid.equals(Ci.nsIFeedContainer) ||
|
||||
@ -407,6 +427,7 @@ function Entry() {
|
||||
this.fields = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag2);
|
||||
this.link = null;
|
||||
this.id = null;
|
||||
this.baseURI = null;
|
||||
}
|
||||
|
||||
@ -444,8 +465,10 @@ Entry.prototype = {
|
||||
mediaContent: null,
|
||||
|
||||
searchLists: {
|
||||
_title: ["title","rss1:title","atom03:title","atom:title"],
|
||||
_title: ["title", "rss1:title", "atom03:title", "atom:title"],
|
||||
link: [["link",strToURI],["rss1:link",strToURI]],
|
||||
id: [["guid", makePropGetter("guid")], "rdf:about",
|
||||
"atom03:id", "atom:id"],
|
||||
_summary: ["description", "rss1:description", "dc:description",
|
||||
"atom03:summary", "atom:summary"],
|
||||
_content: ["content:encoded","atom03:content","atom:content"]
|
||||
@ -453,9 +476,20 @@ Entry.prototype = {
|
||||
|
||||
normalize: function Entry_normalize() {
|
||||
fieldsToObj(this, this.searchLists);
|
||||
|
||||
// Assign Atom link if needed
|
||||
if (bagHasKey(this.fields, "links"))
|
||||
this._atomLinksToURI();
|
||||
|
||||
// The link might be a guid w/ permalink=true
|
||||
if (!this.link && bagHasKey(this.fields, "guid")) {
|
||||
var guid = this.fields.getProperty("guid");
|
||||
if (bagHasKey(guid, "isPermaLink")) {
|
||||
var isPermaLink = new Boolean(guid.getProperty("isPermaLink"));
|
||||
if (isPermaLink)
|
||||
this.link = strToURI(guid.getProperty("guid"));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
@ -1134,6 +1168,7 @@ FeedProcessor.prototype = {
|
||||
this._state = "IN_" + elementInfo.fieldName.toUpperCase();
|
||||
this._docVerified(elementInfo.feedVersion);
|
||||
this._stack.push([this._feed, this._state]);
|
||||
this._mapAttributes(this._feed, attributes);
|
||||
}
|
||||
else {
|
||||
this._state = this._processComplexElement(elementInfo, attributes);
|
||||
@ -1193,7 +1228,7 @@ FeedProcessor.prototype = {
|
||||
function FP__processComplexElement(elementInfo, attributes) {
|
||||
var obj, props, key, prefix;
|
||||
|
||||
// If the container is a feed or entry, it'll need to have its
|
||||
// If the container is an entry/item, it'll need to have its
|
||||
// more esoteric properties put in the 'fields' property bag, and set its
|
||||
// parent.
|
||||
if (elementInfo.containerClass) {
|
||||
@ -1208,15 +1243,7 @@ FeedProcessor.prototype = {
|
||||
props = obj;
|
||||
}
|
||||
|
||||
// Cycle through the attributes, and set our properties using the
|
||||
// prefix:localNames we find in our namespace dictionary.
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
prefix = gNamespaces[attributes.getURI(i)] ?
|
||||
gNamespaces[attributes.getURI(i)] + ":" : "";
|
||||
key = prefix + attributes.getLocalName(i);
|
||||
var val = attributes.getValue(i);
|
||||
props.setPropertyAsAString(key, val);
|
||||
}
|
||||
this._mapAttributes(props, attributes);
|
||||
|
||||
// We should have a container/propertyBag that's had its
|
||||
// attributes processed. Now we need to attach it to its
|
||||
@ -1300,6 +1327,19 @@ FeedProcessor.prototype = {
|
||||
container.replaceElementAt(element, container.length - 1, false);
|
||||
},
|
||||
|
||||
|
||||
_mapAttributes: function FP__mapAttributes(bag, attributes) {
|
||||
// Cycle through the attributes, and set our properties using the
|
||||
// prefix:localNames we find in our namespace dictionary.
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
prefix = gNamespaces[attributes.getURI(i)] ?
|
||||
gNamespaces[attributes.getURI(i)] + ":" : "";
|
||||
key = prefix + attributes.getLocalName(i);
|
||||
var val = attributes.getValue(i);
|
||||
bag.setPropertyAsAString(key, val);
|
||||
}
|
||||
},
|
||||
|
||||
// unknown element values are returned here. See startElement above
|
||||
// for how this works.
|
||||
returnFromExtHandler:
|
||||
|
35
toolkit/components/feeds/test/xml/rfc4287/entry_id.xml
Normal file
35
toolkit/components/feeds/test/xml/rfc4287/entry_id.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
|
||||
Description: atom entry id
|
||||
Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).id == "http://foo.example.com/hmm/ok,2006,07,11";
|
||||
|
||||
-->
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:foo="http://www.example.org"
|
||||
foo:quux="quuux">
|
||||
|
||||
<title>hmm</title>
|
||||
|
||||
<author>
|
||||
<email>hmm@example.com</email>
|
||||
<name>foo</name>
|
||||
</author>
|
||||
<generator version="1.1" uri="http://example.org">Hmm</generator>
|
||||
<author>
|
||||
<email>bar@example.com</email>
|
||||
<name>foo</name>
|
||||
</author>
|
||||
<rights type="xhtml">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
|
||||
</rights>
|
||||
|
||||
|
||||
<entry></entry>
|
||||
|
||||
<entry foo:bar="baz">
|
||||
<title>test</title>
|
||||
<id>http://foo.example.com/hmm/ok,2006,07,11</id>
|
||||
</entry>
|
||||
|
||||
</feed>
|
@ -2,7 +2,7 @@
|
||||
<!--
|
||||
|
||||
Description: atom author name works
|
||||
Expect: feed.fields.getProperty('atom:id') == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
|
||||
Expect: feed.fields.getProperty('atom:id') == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6' && feed.id == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
|
||||
|
||||
-->
|
||||
|
||||
@ -24,4 +24,4 @@ Expect: feed.fields.getProperty('atom:id') == 'urn:uuid:60a76c80-d399-11d9-b93C-
|
||||
<summary>Some text.</summary>
|
||||
</entry>
|
||||
|
||||
</feed>
|
||||
</feed>
|
||||
|
25
toolkit/components/feeds/test/xml/rss1/feed_id.xml
Normal file
25
toolkit/components/feeds/test/xml/rss1/feed_id.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
Description: RSS1 feed w/ feed rdf:about
|
||||
Expect: feed.id == 'http://www.xml.com/xml/news.rss'
|
||||
|
||||
-->
|
||||
<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://purl.org/rss/1.0/"
|
||||
xmlns:dc='http://purl.org/dc/elements/1.1/'>
|
||||
<channel rdf:about="http://www.xml.com/xml/news.rss">
|
||||
<title>Test</title>
|
||||
<link>http://xml.com/pub</link>
|
||||
<dc:description>another description</dc:description>
|
||||
</channel>
|
||||
<item rdf:about="http://example.com/hmm">
|
||||
<title>XML: A Disruptive Technology</title>
|
||||
<link>http://c.moreover.com/click/here.pl?r123</link>
|
||||
<dc:description>
|
||||
XML is placing increasingly heavy loads on the existing technical
|
||||
infrastructure of the Internet.
|
||||
</dc:description>
|
||||
</item>
|
||||
</rdf:RDF>
|
32
toolkit/components/feeds/test/xml/rss1/item_id.xml
Normal file
32
toolkit/components/feeds/test/xml/rss1/item_id.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
Description: RSS1 feed w/ item rdf:about
|
||||
Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).id == 'http://example.com/hmm'
|
||||
|
||||
-->
|
||||
<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://purl.org/rss/1.0/"
|
||||
xmlns:dc='http://purl.org/dc/elements/1.1/'>
|
||||
<channel rdf:about="http://www.xml.com/xml/news.rss">
|
||||
<title>Test</title>
|
||||
<link>http://xml.com/pub</link>
|
||||
<dc:description>another description</dc:description>
|
||||
</channel>
|
||||
<item rdf:about="http://example.com/hmm">
|
||||
<title>XML: A Disruptive Technology</title>
|
||||
<link>http://c.moreover.com/click/here.pl?r123</link>
|
||||
<dc:description>
|
||||
XML is placing increasingly heavy loads on the existing technical
|
||||
infrastructure of the Internet.
|
||||
</dc:description>
|
||||
<!-- <dc:publisher>The O'Reilly Network</dc:publisher>
|
||||
<dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
|
||||
<dc:rights>Copyright © 2000 O'Reilly & Associates, Inc.</dc:rights>
|
||||
<dc:subject>XML</dc:subject>-->
|
||||
</item>
|
||||
<item>
|
||||
|
||||
</item>
|
||||
</rdf:RDF>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
|
||||
Description: item copes with bogus guid
|
||||
Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link == null;
|
||||
|
||||
-->
|
||||
<rss version="2.0" >
|
||||
<channel>
|
||||
<item>
|
||||
|
||||
<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
|
||||
<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
|
||||
<comments>http://example.org</comments>
|
||||
<title>test</title>
|
||||
<guid isPermaLink="true">xorg</guid>
|
||||
<category domain="foo">bar</category>
|
||||
|
||||
<description>I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
|
||||
</channel>
|
||||
</rss>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
|
||||
Description: item guid works
|
||||
Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link.spec == 'http://www.example.org/';
|
||||
|
||||
-->
|
||||
<rss version="2.0" >
|
||||
<channel>
|
||||
<item>
|
||||
|
||||
<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
|
||||
<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
|
||||
<title>test</title>
|
||||
<guid isPermaLink="true">http://www.example.org/</guid>
|
||||
<category domain="foo">bar</category>
|
||||
|
||||
<description>I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
|
||||
</channel>
|
||||
</rss>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
|
||||
Description: item guid works
|
||||
Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).id == 'asdf';
|
||||
|
||||
-->
|
||||
<rss version="2.0" >
|
||||
<channel>
|
||||
<item>
|
||||
|
||||
<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
|
||||
<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
|
||||
<comments>http://example.org</comments>
|
||||
<title>test</title>
|
||||
<guid>asdf</guid>
|
||||
<category domain="foo">bar</category>
|
||||
|
||||
<description>I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
|
||||
</channel>
|
||||
</rss>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
|
||||
Description: item prefers link to guid
|
||||
Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == 'http://link.example.org/';
|
||||
|
||||
-->
|
||||
<rss version="2.0" >
|
||||
<channel>
|
||||
<item>
|
||||
|
||||
<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
|
||||
<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
|
||||
<comments>http://example.org</comments>
|
||||
<title>test</title>
|
||||
<guid isPermaLink="true">http://www.example.org</guid>
|
||||
<link>http://link.example.org/</link>
|
||||
<category domain="foo">bar</category>
|
||||
|
||||
<description>I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
|
||||
</channel>
|
||||
</rss>
|
Loading…
x
Reference in New Issue
Block a user