Convert feed processor data away from XPCOM
This changes the feed processor XPCOM array and property bags to native arrays and objects.
This commit is contained in:
parent
75eb8c51d4
commit
be80598c6b
2 changed files with 110 additions and 190 deletions
|
@ -108,7 +108,7 @@ Zotero.FeedReader = function (url) {
|
||||||
let items = this._feed.items;
|
let items = this._feed.items;
|
||||||
if (items && items.length) {
|
if (items && items.length) {
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
let item = items.queryElementAt(i, Components.interfaces.nsIFeedEntry);
|
let item = items[i];
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
|
|
||||||
let feedItem = Zotero.FeedReader._getFeedItem(item, this._feedProperties);
|
let feedItem = Zotero.FeedReader._getFeedItem(item, this._feedProperties);
|
||||||
|
@ -295,7 +295,7 @@ Zotero.FeedReader._processCreators = function (feedEntry, field, role) {
|
||||||
try {
|
try {
|
||||||
let personArr = feedEntry[field]; // Seems like this part can throw if there is no author data in the feed
|
let personArr = feedEntry[field]; // Seems like this part can throw if there is no author data in the feed
|
||||||
for (let i = 0; i < personArr.length; i++) {
|
for (let i = 0; i < personArr.length; i++) {
|
||||||
let person = personArr.queryElementAt(i, Components.interfaces.nsIFeedPerson);
|
let person = personArr[i];
|
||||||
if (!person || !person.name) continue;
|
if (!person || !person.name) continue;
|
||||||
|
|
||||||
let name = Zotero.Utilities.cleanTags(Zotero.Utilities.trimInternal(person.name));
|
let name = Zotero.Utilities.cleanTags(Zotero.Utilities.trimInternal(person.name));
|
||||||
|
@ -321,8 +321,6 @@ Zotero.FeedReader._processCreators = function (feedEntry, field, role) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e.result != Components.results.NS_ERROR_FAILURE) throw e;
|
|
||||||
|
|
||||||
if (field != 'authors') return [];
|
if (field != 'authors') return [];
|
||||||
|
|
||||||
// ieeexplore places these in "authors"... sigh
|
// ieeexplore places these in "authors"... sigh
|
||||||
|
@ -502,18 +500,16 @@ let ns = {
|
||||||
};
|
};
|
||||||
Zotero.FeedReader._getFeedField = function (feedEntry, field, namespace) {
|
Zotero.FeedReader._getFeedField = function (feedEntry, field, namespace) {
|
||||||
let prefix = namespace ? ns[namespace] || 'null' : '';
|
let prefix = namespace ? ns[namespace] || 'null' : '';
|
||||||
try {
|
if (feedEntry.fields[prefix + field]) {
|
||||||
return feedEntry.fields.getPropertyAsAUTF8String(prefix + field);
|
return feedEntry.fields[prefix + field];
|
||||||
}
|
}
|
||||||
catch (e) {}
|
|
||||||
|
|
||||||
try {
|
if (namespace && !ns[namespace]) {
|
||||||
if (namespace && !ns[namespace]) {
|
prefix = namespace + ':';
|
||||||
prefix = namespace + ':';
|
if (feedEntry.fields[prefix + field]) {
|
||||||
return feedEntry.fields.getPropertyAsAUTF8String(prefix + field);
|
return feedEntry.fields[prefix + field];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) { }
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -523,9 +519,9 @@ Zotero.FeedReader._getEnclosedItems = function (feedEntry) {
|
||||||
|
|
||||||
if (feedEntry.enclosures) {
|
if (feedEntry.enclosures) {
|
||||||
for (let i = 0; i < feedEntry.enclosures.length; i++) {
|
for (let i = 0; i < feedEntry.enclosures.length; i++) {
|
||||||
let elem = feedEntry.enclosures.queryElementAt(0, Components.interfaces.nsIPropertyBag2);
|
let elem = feedEntry.enclosures[0];
|
||||||
if (elem.get('url')) {
|
if (elem.url) {
|
||||||
let enclosedItem = { url: elem.get('url'), contentType: elem.get('type') || '' };
|
let enclosedItem = { url: elem.url, contentType: elem.type || '' };
|
||||||
enclosedItems.push(enclosedItem);
|
enclosedItems.push(enclosedItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@ function LOG(str) {
|
||||||
Zotero.debug("Feed Processor: " + str);
|
Zotero.debug("Feed Processor: " + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BAG_CONTRACTID = "@mozilla.org/hash-property-bag;1";
|
|
||||||
const ARRAY_CONTRACTID = "@mozilla.org/array;1";
|
|
||||||
const SAX_CONTRACTID = "@mozilla.org/saxparser/xmlreader;1";
|
const SAX_CONTRACTID = "@mozilla.org/saxparser/xmlreader;1";
|
||||||
const PARSERUTILS_CONTRACTID = "@mozilla.org/parserutils;1";
|
const PARSERUTILS_CONTRACTID = "@mozilla.org/parserutils;1";
|
||||||
|
|
||||||
|
@ -74,12 +72,12 @@ const IANA_URI = "http://www.iana.org/assignments/relation/";
|
||||||
function findAtomLinks(rel, links) {
|
function findAtomLinks(rel, links) {
|
||||||
var rvLinks = [];
|
var rvLinks = [];
|
||||||
for (var i = 0; i < links.length; ++i) {
|
for (var i = 0; i < links.length; ++i) {
|
||||||
var linkElement = links.queryElementAt(i, Ci.nsIPropertyBag2);
|
var linkElement = links[i];
|
||||||
// atom:link MUST have @href
|
// atom:link MUST have @href
|
||||||
if (bagHasKey(linkElement, "href")) {
|
if (linkElement.href) {
|
||||||
var relAttribute = null;
|
var relAttribute = null;
|
||||||
if (bagHasKey(linkElement, "rel")) {
|
if (linkElement.rel) {
|
||||||
relAttribute = linkElement.getPropertyAsAString("rel");
|
relAttribute = linkElement.rel;
|
||||||
}
|
}
|
||||||
if ((!relAttribute && rel == "alternate") || relAttribute == rel) {
|
if ((!relAttribute && rel == "alternate") || relAttribute == rel) {
|
||||||
rvLinks.push(linkElement);
|
rvLinks.push(linkElement);
|
||||||
|
@ -103,34 +101,9 @@ function xmlEscape(s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayContains(array, element) {
|
|
||||||
for (var i = 0; i < array.length; ++i) {
|
|
||||||
if (array[i] == element) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX add hasKey to nsIPropertyBag
|
|
||||||
function bagHasKey(bag, key) {
|
|
||||||
try {
|
|
||||||
bag.getProperty(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makePropGetter(key) {
|
function makePropGetter(key) {
|
||||||
return function (bag) {
|
return function(bag) {
|
||||||
try {
|
return bag[key];
|
||||||
return bag.getProperty(key);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,12 +152,12 @@ FeedResult.prototype = {
|
||||||
function Feed() {
|
function Feed() {
|
||||||
this.subtitle = null;
|
this.subtitle = null;
|
||||||
this.title = null;
|
this.title = null;
|
||||||
this.items = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.items = [];
|
||||||
this.link = null;
|
this.link = null;
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.generator = null;
|
this.generator = null;
|
||||||
this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.authors = [];
|
||||||
this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.contributors = [];
|
||||||
this.baseURI = null;
|
this.baseURI = null;
|
||||||
this.enclosureCount = 0;
|
this.enclosureCount = 0;
|
||||||
this.type = Ci.nsIFeed.TYPE_FEED;
|
this.type = Ci.nsIFeed.TYPE_FEED;
|
||||||
|
@ -226,10 +199,10 @@ Feed.prototype = {
|
||||||
normalize: function () {
|
normalize: function () {
|
||||||
fieldsToObj(this, this.searchLists);
|
fieldsToObj(this, this.searchLists);
|
||||||
if (this.skipDays) {
|
if (this.skipDays) {
|
||||||
this.skipDays = this.skipDays.getProperty("days");
|
this.skipDays = this.skipDays.days;
|
||||||
}
|
}
|
||||||
if (this.skipHours) {
|
if (this.skipHours) {
|
||||||
this.skipHours = this.skipHours.getProperty("hours");
|
this.skipHours = this.skipHours.hours;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.updated) {
|
if (this.updated) {
|
||||||
|
@ -237,14 +210,14 @@ Feed.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign Atom link if needed
|
// Assign Atom link if needed
|
||||||
if (bagHasKey(this.fields, "links")) {
|
if (this.fields.links) {
|
||||||
this._atomLinksToURI();
|
this._atomLinksToURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._calcEnclosureCountAndFeedType();
|
this._calcEnclosureCountAndFeedType();
|
||||||
|
|
||||||
// Resolve relative image links
|
// Resolve relative image links
|
||||||
if (this.image && bagHasKey(this.image, "url")) {
|
if (this.image && this.image.url) {
|
||||||
this._resolveImageLink();
|
this._resolveImageLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,16 +232,15 @@ Feed.prototype = {
|
||||||
var otherCount = 0;
|
var otherCount = 0;
|
||||||
|
|
||||||
for (var i = 0; i < this.items.length; ++i) {
|
for (var i = 0; i < this.items.length; ++i) {
|
||||||
var entry = this.items.queryElementAt(i, Ci.nsIFeedEntry);
|
var entry = this.items[i];
|
||||||
entry.QueryInterface(Ci.nsIFeedContainer);
|
|
||||||
|
|
||||||
if (entry.enclosures && entry.enclosures.length > 0) {
|
if (entry.enclosures && entry.enclosures.length > 0) {
|
||||||
++entriesWithEnclosures;
|
++entriesWithEnclosures;
|
||||||
|
|
||||||
for (var e = 0; e < entry.enclosures.length; ++e) {
|
for (var e = 0; e < entry.enclosures.length; ++e) {
|
||||||
var enc = entry.enclosures.queryElementAt(e, Ci.nsIWritablePropertyBag2);
|
var enc = entry.enclosures[e];
|
||||||
if (enc.hasKey("type")) {
|
if (enc.type) {
|
||||||
var enctype = enc.get("type");
|
var enctype = enc.type;
|
||||||
|
|
||||||
if (/^audio/.test(enctype)) {
|
if (/^audio/.test(enctype)) {
|
||||||
++audioCount;
|
++audioCount;
|
||||||
|
@ -317,13 +289,13 @@ Feed.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_atomLinksToURI: function () {
|
_atomLinksToURI: function () {
|
||||||
var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
|
var links = this.fields.links;
|
||||||
var alternates = findAtomLinks("alternate", links);
|
var alternates = findAtomLinks("alternate", links);
|
||||||
if (alternates.length > 0) {
|
if (alternates.length > 0) {
|
||||||
var href = alternates[0].getPropertyAsAString("href");
|
var href = alternates[0].href;
|
||||||
var base;
|
var base;
|
||||||
if (bagHasKey(alternates[0], "xml:base")) {
|
if (alternates[0]["xml:base"]) {
|
||||||
base = alternates[0].getPropertyAsAString("xml:base");
|
base = alternates[0]["xml:base"];
|
||||||
}
|
}
|
||||||
this.link = this._resolveURI(href, base);
|
this.link = this._resolveURI(href, base);
|
||||||
}
|
}
|
||||||
|
@ -331,12 +303,12 @@ Feed.prototype = {
|
||||||
|
|
||||||
_resolveImageLink: function () {
|
_resolveImageLink: function () {
|
||||||
var base;
|
var base;
|
||||||
if (bagHasKey(this.image, "xml:base")) {
|
if (this.image["xml:base"]) {
|
||||||
base = this.image.getPropertyAsAString("xml:base");
|
base = this.image["xml:base"];
|
||||||
}
|
}
|
||||||
var url = this._resolveURI(this.image.getPropertyAsAString("url"), base);
|
var url = this._resolveURI(this.image.url, base);
|
||||||
if (url) {
|
if (url) {
|
||||||
this.image.setPropertyAsAString("url", url.spec);
|
this.image.url = url.spec;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -357,9 +329,9 @@ Feed.prototype = {
|
||||||
_resetBagMembersToRawText: function (fieldLists) {
|
_resetBagMembersToRawText: function (fieldLists) {
|
||||||
for (var i = 0; i < fieldLists.length; i++) {
|
for (var i = 0; i < fieldLists.length; i++) {
|
||||||
for (var j = 0; j < fieldLists[i].length; j++) {
|
for (var j = 0; j < fieldLists[i].length; j++) {
|
||||||
if (bagHasKey(this.fields, fieldLists[i][j])) {
|
if (this.fields[fieldLists[i][j]]) {
|
||||||
var textConstruct = this.fields.getProperty(fieldLists[i][j]);
|
var textConstruct = this.fields[fieldLists[i][j]];
|
||||||
this.fields.setPropertyAsAString(fieldLists[i][j], textConstruct.text);
|
this.fields[fieldLists[i][j]] = textConstruct.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,14 +343,14 @@ function Entry() {
|
||||||
this.summary = null;
|
this.summary = null;
|
||||||
this.content = null;
|
this.content = null;
|
||||||
this.title = null;
|
this.title = null;
|
||||||
this.fields = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
|
this.fields = {};
|
||||||
this.link = null;
|
this.link = null;
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.baseURI = null;
|
this.baseURI = null;
|
||||||
this.updated = null;
|
this.updated = null;
|
||||||
this.published = null;
|
this.published = null;
|
||||||
this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.authors = [];
|
||||||
this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.contributors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry.prototype = {
|
Entry.prototype = {
|
||||||
|
@ -420,7 +392,7 @@ Entry.prototype = {
|
||||||
fieldsToObj(this, this.searchLists);
|
fieldsToObj(this, this.searchLists);
|
||||||
|
|
||||||
// Assign Atom link if needed
|
// Assign Atom link if needed
|
||||||
if (bagHasKey(this.fields, "links")) {
|
if (this.fields.links) {
|
||||||
this._atomLinksToURI();
|
this._atomLinksToURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,16 +400,16 @@ Entry.prototype = {
|
||||||
this._populateEnclosures();
|
this._populateEnclosures();
|
||||||
|
|
||||||
// The link might be a guid w/ permalink=true
|
// The link might be a guid w/ permalink=true
|
||||||
if (!this.link && bagHasKey(this.fields, "guid")) {
|
if (!this.link && this.fields.guid) {
|
||||||
var guid = this.fields.getProperty("guid");
|
var guid = this.fields.guid;
|
||||||
var isPermaLink = true;
|
var isPermaLink = true;
|
||||||
|
|
||||||
if (bagHasKey(guid, "isPermaLink")) {
|
if (guid.isPermaLink) {
|
||||||
isPermaLink = guid.getProperty("isPermaLink").toLowerCase() != "false";
|
isPermaLink = guid.isPermaLink.toLowerCase() != "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guid && isPermaLink) {
|
if (guid && isPermaLink) {
|
||||||
this.link = strToURI(guid.getProperty("guid"));
|
this.link = strToURI(guid.guid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,27 +428,27 @@ Entry.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_populateEnclosures: function () {
|
_populateEnclosures: function () {
|
||||||
if (bagHasKey(this.fields, "links")) {
|
if (this.fields.links) {
|
||||||
this._atomLinksToEnclosures();
|
this._atomLinksToEnclosures();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add RSS2 enclosure to enclosures
|
// Add RSS2 enclosure to enclosures
|
||||||
if (bagHasKey(this.fields, "enclosure")) {
|
if (this.fields.enclosure) {
|
||||||
this._enclosureToEnclosures();
|
this._enclosureToEnclosures();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add media:content to enclosures
|
// Add media:content to enclosures
|
||||||
if (bagHasKey(this.fields, "mediacontent")) {
|
if (this.fields.mediacontent) {
|
||||||
this._mediaToEnclosures("mediacontent");
|
this._mediaToEnclosures("mediacontent");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add media:thumbnail to enclosures
|
// Add media:thumbnail to enclosures
|
||||||
if (bagHasKey(this.fields, "mediathumbnail")) {
|
if (this.fields.mediathumbnail) {
|
||||||
this._mediaToEnclosures("mediathumbnail");
|
this._mediaToEnclosures("mediathumbnail");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add media:content in media:group to enclosures
|
// Add media:content in media:group to enclosures
|
||||||
if (bagHasKey(this.fields, "mediagroup")) {
|
if (this.fields.mediagroup) {
|
||||||
this._mediaToEnclosures("mediagroup", "mediacontent");
|
this._mediaToEnclosures("mediagroup", "mediacontent");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -486,7 +458,7 @@ Entry.prototype = {
|
||||||
_addToEnclosures: function (newEnc) {
|
_addToEnclosures: function (newEnc) {
|
||||||
// items we add to the enclosures array get displayed in the FeedWriter and
|
// items we add to the enclosures array get displayed in the FeedWriter and
|
||||||
// they must have non-empty urls.
|
// they must have non-empty urls.
|
||||||
if (!bagHasKey(newEnc, "url") || newEnc.getPropertyAsAString("url") == "") {
|
if (!newEnc.url || newEnc.url == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,40 +466,37 @@ Entry.prototype = {
|
||||||
this.__enclosureMap = {};
|
this.__enclosureMap = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousEnc = this.__enclosureMap[newEnc.getPropertyAsAString("url")];
|
var previousEnc = this.__enclosureMap[newEnc.url];
|
||||||
|
|
||||||
if (previousEnc != undefined) {
|
if (previousEnc != undefined) {
|
||||||
previousEnc.QueryInterface(Ci.nsIWritablePropertyBag2);
|
if (!previousEnc.type && newEnc.type) {
|
||||||
|
previousEnc.type = newEnc.type;
|
||||||
if (!bagHasKey(previousEnc, "type") && bagHasKey(newEnc, "type")) {
|
|
||||||
previousEnc.setPropertyAsAString("type", newEnc.getPropertyAsAString("type"));
|
|
||||||
try {
|
try {
|
||||||
let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(newEnc.getPropertyAsAString("type"), null);
|
let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(newEnc.type, null);
|
||||||
if (handlerInfoWrapper && handlerInfoWrapper.description) {
|
if (handlerInfoWrapper && handlerInfoWrapper.description) {
|
||||||
previousEnc.setPropertyAsAString("typeDesc", handlerInfoWrapper.description);
|
previousEnc.typeDesc = handlerInfoWrapper.description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ext) {}
|
catch (ext) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bagHasKey(previousEnc, "length") && bagHasKey(newEnc, "length")) {
|
if (!previousEnc.length && newEnc.length) {
|
||||||
previousEnc.setPropertyAsAString("length", newEnc.getPropertyAsAString("length"));
|
previousEnc.length = newEnc.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.enclosures === null) {
|
if (this.enclosures === null) {
|
||||||
this.enclosures = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
|
this.enclosures = [];
|
||||||
this.enclosures.QueryInterface(Ci.nsIMutableArray);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enclosures.appendElement(newEnc);
|
this.enclosures.push(newEnc);
|
||||||
this.__enclosureMap[newEnc.getPropertyAsAString("url")] = newEnc;
|
this.__enclosureMap[newEnc.url] = newEnc;
|
||||||
},
|
},
|
||||||
|
|
||||||
_atomLinksToEnclosures: function () {
|
_atomLinksToEnclosures: function () {
|
||||||
var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
|
var links = this.fields.links;
|
||||||
var encLinks = findAtomLinks("enclosure", links);
|
var encLinks = findAtomLinks("enclosure", links);
|
||||||
if (encLinks.length == 0) {
|
if (encLinks.length == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -537,19 +506,19 @@ Entry.prototype = {
|
||||||
var link = encLinks[i];
|
var link = encLinks[i];
|
||||||
|
|
||||||
// an enclosure must have an href
|
// an enclosure must have an href
|
||||||
if (!(link.getProperty("href"))) {
|
if (!link.href) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
|
var enc = {};
|
||||||
|
|
||||||
// copy Atom bits over to equivalent enclosure bits
|
// copy Atom bits over to equivalent enclosure bits
|
||||||
enc.setPropertyAsAString("url", link.getPropertyAsAString("href"));
|
enc.url = link.href;
|
||||||
if (bagHasKey(link, "type")) {
|
if (link.type) {
|
||||||
enc.setPropertyAsAString("type", link.getPropertyAsAString("type"));
|
enc.type = link.type;
|
||||||
}
|
}
|
||||||
if (bagHasKey(link, "length")) {
|
if (link.length) {
|
||||||
enc.setPropertyAsAString("length", link.getPropertyAsAString("length"));
|
enc.length = link.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._addToEnclosures(enc);
|
this._addToEnclosures(enc);
|
||||||
|
@ -557,9 +526,9 @@ Entry.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_enclosureToEnclosures: function () {
|
_enclosureToEnclosures: function () {
|
||||||
var enc = this.fields.getPropertyAsInterface("enclosure", Ci.nsIPropertyBag2);
|
var enc = this.fields.enclosure;
|
||||||
|
|
||||||
if (!(enc.getProperty("url"))) {
|
if (!enc.url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,37 +541,37 @@ Entry.prototype = {
|
||||||
// If a contentType is specified, the mediaType is a simple propertybag,
|
// If a contentType is specified, the mediaType is a simple propertybag,
|
||||||
// and the contentType is an array inside it.
|
// and the contentType is an array inside it.
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
var group = this.fields.getPropertyAsInterface(mediaType, Ci.nsIPropertyBag2);
|
var group = this.fields[mediaType];
|
||||||
content = group.getPropertyAsInterface(contentType, Ci.nsIArray);
|
content = group[contentType];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
content = this.fields.getPropertyAsInterface(mediaType, Ci.nsIArray);
|
content = this.fields[mediaType];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < content.length; ++i) {
|
for (var i = 0; i < content.length; ++i) {
|
||||||
var contentElement = content.queryElementAt(i, Ci.nsIWritablePropertyBag2);
|
var contentElement = content[i];
|
||||||
|
|
||||||
// media:content don't require url, but if it's not there, we should
|
// media:content don't require url, but if it's not there, we should
|
||||||
// skip it.
|
// skip it.
|
||||||
if (!bagHasKey(contentElement, "url")) {
|
if (!contentElement.url) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
|
var enc = {};
|
||||||
|
|
||||||
// copy media:content bits over to equivalent enclosure bits
|
// copy media:content bits over to equivalent enclosure bits
|
||||||
enc.setPropertyAsAString("url", contentElement.getPropertyAsAString("url"));
|
enc.url = contentElement.url;
|
||||||
if (bagHasKey(contentElement, "type")) {
|
if (contentElement.type) {
|
||||||
enc.setPropertyAsAString("type", contentElement.getPropertyAsAString("type"));
|
enc.type = contentElement.type;
|
||||||
}
|
}
|
||||||
else if (mediaType == "mediathumbnail") {
|
else if (mediaType == "mediathumbnail") {
|
||||||
// thumbnails won't have a type, but default to image types
|
// thumbnails won't have a type, but default to image types
|
||||||
enc.setPropertyAsAString("type", "image/*");
|
enc.type = "image/*";
|
||||||
enc.setPropertyAsBool("thumbnail", true);
|
enc.thumbnail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bagHasKey(contentElement, "fileSize")) {
|
if (contentElement.fileSize) {
|
||||||
enc.setPropertyAsAString("length", contentElement.getPropertyAsAString("fileSize"));
|
enc.length = contentElement.fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._addToEnclosures(enc);
|
this._addToEnclosures(enc);
|
||||||
|
@ -721,11 +690,7 @@ function fieldsToObj(container, fields) {
|
||||||
props = searchList[i];
|
props = searchList[i];
|
||||||
prop = null;
|
prop = null;
|
||||||
field = isArray(props) ? props[0] : props;
|
field = isArray(props) ? props[0] : props;
|
||||||
try {
|
prop = container.fields[field];
|
||||||
prop = container.fields.getProperty(field);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
}
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
prop = isArray(props) ? props[1](prop) : prop;
|
prop = isArray(props) ? props[1](prop) : prop;
|
||||||
container[key] = prop;
|
container[key] = prop;
|
||||||
|
@ -734,39 +699,27 @@ function fieldsToObj(container, fields) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Lower cases an element's localName property
|
|
||||||
* @param element A DOM element.
|
|
||||||
*
|
|
||||||
* @returns The lower case localName property of the specified element
|
|
||||||
*/
|
|
||||||
function LC(element) {
|
|
||||||
return element.localName.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move these post-processor functions
|
|
||||||
// create a generator element
|
// create a generator element
|
||||||
function atomGenerator(s, generator) {
|
function atomGenerator(s, generator) {
|
||||||
generator.QueryInterface(Ci.nsIFeedGenerator);
|
|
||||||
generator.agent = s.trim();
|
generator.agent = s.trim();
|
||||||
return generator;
|
return generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post-process atom:logo to create an RSS2-like structure
|
// post-process atom:logo to create an RSS2-like structure
|
||||||
function atomLogo(s, logo) {
|
function atomLogo(s, logo) {
|
||||||
logo.setPropertyAsAString("url", s.trim());
|
logo.url = s.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
// post-process an RSS category, map it to the Atom fields.
|
// post-process an RSS category, map it to the Atom fields.
|
||||||
function rssCatTerm(s, cat) {
|
function rssCatTerm(s, cat) {
|
||||||
// add slash handling?
|
// add slash handling?
|
||||||
cat.setPropertyAsAString("term", s.trim());
|
cat.term = s.trim();
|
||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post-process a GUID
|
// post-process a GUID
|
||||||
function rssGuid(s, guid) {
|
function rssGuid(s, guid) {
|
||||||
guid.setPropertyAsAString("guid", s.trim());
|
guid.guid = s.trim();
|
||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,7 +737,6 @@ function rssGuid(s, guid) {
|
||||||
// fields.
|
// fields.
|
||||||
//
|
//
|
||||||
function rssAuthor(s, author) {
|
function rssAuthor(s, author) {
|
||||||
author.QueryInterface(Ci.nsIFeedPerson);
|
|
||||||
// check for RSS2 string format
|
// check for RSS2 string format
|
||||||
var chars = s.trim();
|
var chars = s.trim();
|
||||||
var matches = chars.match(/(.*)\((.*)\)/);
|
var matches = chars.match(/(.*)\((.*)\)/);
|
||||||
|
@ -818,17 +770,6 @@ function rssAuthor(s, author) {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// skipHours and skipDays map to arrays, so we need to change the
|
|
||||||
// string to an nsISupports in order to stick it in there.
|
|
||||||
//
|
|
||||||
function rssArrayElement(s) {
|
|
||||||
var str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
|
||||||
str.data = s;
|
|
||||||
str.QueryInterface(Ci.nsISupportsString);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries parsing a string through the JavaScript Date object.
|
* Tries parsing a string through the JavaScript Date object.
|
||||||
* @param aDateString
|
* @param aDateString
|
||||||
|
@ -1045,7 +986,7 @@ function WrapperElementInfo(fieldName) {
|
||||||
function FeedProcessor() {
|
function FeedProcessor() {
|
||||||
this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader);
|
this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader);
|
||||||
this._buf = "";
|
this._buf = "";
|
||||||
this._feed = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
|
this._feed = {};
|
||||||
this._handlerStack = [];
|
this._handlerStack = [];
|
||||||
this._xmlBaseStack = []; // sparse array keyed to nesting depth
|
this._xmlBaseStack = []; // sparse array keyed to nesting depth
|
||||||
this._depth = 0;
|
this._depth = 0;
|
||||||
|
@ -1129,11 +1070,11 @@ function FeedProcessor() {
|
||||||
},
|
},
|
||||||
|
|
||||||
"IN_SKIPDAYS": {
|
"IN_SKIPDAYS": {
|
||||||
"day": new ElementInfo("days", null, rssArrayElement, true),
|
"day": new ElementInfo("days", null, null, true),
|
||||||
},
|
},
|
||||||
|
|
||||||
"IN_SKIPHOURS": {
|
"IN_SKIPHOURS": {
|
||||||
"hour": new ElementInfo("hours", null, rssArrayElement, true),
|
"hour": new ElementInfo("hours", null, null, true),
|
||||||
},
|
},
|
||||||
|
|
||||||
"IN_MEDIAGROUP": {
|
"IN_MEDIAGROUP": {
|
||||||
|
@ -1476,7 +1417,7 @@ FeedProcessor.prototype = {
|
||||||
obj.attributes = attributes; // just set the SAX attributes
|
obj.attributes = attributes; // just set the SAX attributes
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
obj = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
|
obj = {};
|
||||||
this._mapAttributes(obj, attributes);
|
this._mapAttributes(obj, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1489,27 +1430,15 @@ FeedProcessor.prototype = {
|
||||||
var container = this._stack[this._stack.length - 1][0];
|
var container = this._stack[this._stack.length - 1][0];
|
||||||
|
|
||||||
// Check to see if it has the property
|
// Check to see if it has the property
|
||||||
var prop;
|
var prop = container[elementInfo.fieldName];
|
||||||
try {
|
|
||||||
prop = container.getProperty(elementInfo.fieldName);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elementInfo.isArray) {
|
if (elementInfo.isArray) {
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
container.setPropertyAsInterface(
|
container[elementInfo.fieldName] = [];
|
||||||
elementInfo.fieldName,
|
|
||||||
Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newProp = container.getProperty(elementInfo.fieldName);
|
newProp = container[elementInfo.fieldName];
|
||||||
// XXX This QI should not be necessary, but XPConnect seems to fly
|
newProp.push(obj);
|
||||||
// off the handle in the browser, and loses track of the interface
|
|
||||||
// on large files. Bug 335638.
|
|
||||||
newProp.QueryInterface(Ci.nsIMutableArray);
|
|
||||||
newProp.appendElement(obj);
|
|
||||||
|
|
||||||
// If new object is an nsIFeedContainer, we want to deal with
|
// If new object is an nsIFeedContainer, we want to deal with
|
||||||
// its member nsIPropertyBag instead.
|
// its member nsIPropertyBag instead.
|
||||||
|
@ -1520,9 +1449,9 @@ FeedProcessor.prototype = {
|
||||||
else {
|
else {
|
||||||
// If it doesn't, set it.
|
// If it doesn't, set it.
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
container.setPropertyAsInterface(elementInfo.fieldName, obj);
|
container[elementInfo.fieldName] = obj;
|
||||||
}
|
}
|
||||||
newProp = container.getProperty(elementInfo.fieldName);
|
newProp = container[elementInfo.fieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
// make our new state name, and push the property onto the stack
|
// make our new state name, and push the property onto the stack
|
||||||
|
@ -1545,7 +1474,7 @@ FeedProcessor.prototype = {
|
||||||
// If it's an array and we have to post-process,
|
// If it's an array and we have to post-process,
|
||||||
// grab the last element
|
// grab the last element
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
element = container.queryElementAt(container.length - 1, Ci.nsISupports);
|
element = container[container.length - 1];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
element = container;
|
element = container;
|
||||||
|
@ -1564,7 +1493,7 @@ FeedProcessor.prototype = {
|
||||||
|
|
||||||
// If it's an array, re-set the last element
|
// If it's an array, re-set the last element
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
container.replaceElementAt(element, container.length - 1);
|
container[container.length - 1] = element;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1588,7 +1517,7 @@ FeedProcessor.prototype = {
|
||||||
for (var i = 0; i < attributes.length; ++i) {
|
for (var i = 0; i < attributes.length; ++i) {
|
||||||
var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i);
|
var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i);
|
||||||
var val = attributes.getValue(i);
|
var val = attributes.getValue(i);
|
||||||
bag.setPropertyAsAString(key, val);
|
bag[key] = val;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1638,13 +1567,8 @@ FeedProcessor.prototype = {
|
||||||
var contract = this._handlerStack[this._depth].containerClass;
|
var contract = this._handlerStack[this._depth].containerClass;
|
||||||
// check if it's something specific, but not an entry
|
// check if it's something specific, but not an entry
|
||||||
if (contract && contract != Entry) {
|
if (contract && contract != Entry) {
|
||||||
var el = container.queryElementAt(container.length - 1,
|
var el = container[container.length - 1];
|
||||||
Ci.nsIFeedElementBase);
|
if (contract != Person) {
|
||||||
// XXX there must be a way to flatten these interfaces
|
|
||||||
if (contract == Person) {
|
|
||||||
el.QueryInterface(Ci.nsIFeedPerson);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return; // don't know about this interface
|
return; // don't know about this interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1679,7 +1603,7 @@ FeedProcessor.prototype = {
|
||||||
// the rest of the function deals with entry- and feed-level stuff
|
// the rest of the function deals with entry- and feed-level stuff
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
container = container.queryElementAt(container.length - 1, Ci.nsIWritablePropertyBag2);
|
container = container[container.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the buffer our new property
|
// Make the buffer our new property
|
||||||
|
@ -1716,10 +1640,10 @@ FeedProcessor.prototype = {
|
||||||
}
|
}
|
||||||
newProp.type = type;
|
newProp.type = type;
|
||||||
newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
|
newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
|
||||||
container.setPropertyAsInterface(propName, newProp);
|
container[propName] = newProp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
container.setPropertyAsAString(propName, chars);
|
container[propName] = chars;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1743,7 +1667,7 @@ FeedProcessor.prototype = {
|
||||||
newProp.text = chars;
|
newProp.text = chars;
|
||||||
newProp.type = "xhtml";
|
newProp.type = "xhtml";
|
||||||
newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
|
newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
|
||||||
container.setPropertyAsInterface(this._prefixForNS(uri) + localName, newProp);
|
container[this._prefixForNS(uri) + localName] = newProp;
|
||||||
|
|
||||||
// XHTML will cause us to peek too far. The XHTML handler will
|
// XHTML will cause us to peek too far. The XHTML handler will
|
||||||
// send us an end element to call. RFC4287-valid feeds allow a
|
// send us an end element to call. RFC4287-valid feeds allow a
|
||||||
|
|
Loading…
Add table
Reference in a new issue