From 71dc4e9bf9286d02e527b66ab3ea62aae203856c Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 7 May 2021 14:07:40 +0100 Subject: [PATCH] Convert feed processor indentation to Zotero style This adjust feed processor indentation to match Zotero conventions for tabs and continuous indents in blocks. --- resource/feeds/FeedProcessor.js | 2603 +++++++++++------------ resource/feeds/nsIFeed.idl | 119 +- resource/feeds/nsIFeedContainer.idl | 109 +- resource/feeds/nsIFeedElementBase.idl | 21 +- resource/feeds/nsIFeedEntry.idl | 51 +- resource/feeds/nsIFeedGenerator.idl | 25 +- resource/feeds/nsIFeedListener.idl | 117 +- resource/feeds/nsIFeedPerson.idl | 25 +- resource/feeds/nsIFeedProcessor.idl | 43 +- resource/feeds/nsIFeedResult.idl | 87 +- resource/feeds/nsIFeedTextConstruct.idl | 63 +- 11 files changed, 1626 insertions(+), 1637 deletions(-) diff --git a/resource/feeds/FeedProcessor.js b/resource/feeds/FeedProcessor.js index 6daf8d70af..7d64618bbf 100644 --- a/resource/feeds/FeedProcessor.js +++ b/resource/feeds/FeedProcessor.js @@ -1,10 +1,9 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ function LOG(str) { - dump("*** " + str + "\n"); + dump("*** " + str + "\n"); } ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -24,11 +23,11 @@ const ENTRY_CLASSID = Components.ID("{8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f}"); const ENTRY_CLASSNAME = "Feed Entry"; const TEXTCONSTRUCT_CONTRACTID = "@mozilla.org/feed-textconstruct;1"; const TEXTCONSTRUCT_CLASSID = - Components.ID("{b992ddcd-3899-4320-9909-924b3e72c922}"); + Components.ID("{b992ddcd-3899-4320-9909-924b3e72c922}"); const TEXTCONSTRUCT_CLASSNAME = "Feed Text Construct"; const GENERATOR_CONTRACTID = "@mozilla.org/feed-generator;1"; const GENERATOR_CLASSID = - Components.ID("{414af362-9ad8-4296-898e-62247f25a20e}"); + Components.ID("{414af362-9ad8-4296-898e-62247f25a20e}"); const GENERATOR_CLASSNAME = "Feed Generator"; const PERSON_CONTRACTID = "@mozilla.org/feed-person;1"; const PERSON_CLASSID = Components.ID("{95c963b7-20b2-11db-92f6-001422106990}"); @@ -47,46 +46,46 @@ const RSS090NS = "http://my.netscape.com/rdf/simple/0.9/"; /** *** Some general utils *****/ function strToURI(link, base) { - base = base || null; - try { - return Services.io.newURI(link, null, base); - } catch (e) { - return null; - } + base = base || null; + try { + return Services.io.newURI(link, null, base); + } catch (e) { + return null; + } } function isArray(a) { - return isObject(a) && a.constructor == Array; + return isObject(a) && a.constructor == Array; } function isObject(a) { - return (a && typeof a == "object") || isFunction(a); + return (a && typeof a == "object") || isFunction(a); } function isFunction(a) { - return typeof a == "function"; + return typeof a == "function"; } function isIID(a, iid) { - var rv = false; - try { - a.QueryInterface(iid); - rv = true; - } catch (e) { - } - return rv; + var rv = false; + try { + a.QueryInterface(iid); + rv = true; + } catch (e) { + } + return rv; } function isIArray(a) { - return isIID(a, Ci.nsIArray); + return isIID(a, Ci.nsIArray); } function isIFeedContainer(a) { - return isIID(a, Ci.nsIFeedContainer); + return isIID(a, Ci.nsIFeedContainer); } function stripTags(someHTML) { - return someHTML.replace(/<[^>]+>/g, ""); + return someHTML.replace(/<[^>]+>/g, ""); } /** @@ -95,604 +94,604 @@ function stripTags(someHTML) { */ const IANA_URI = "http://www.iana.org/assignments/relation/"; function findAtomLinks(rel, links) { - var rvLinks = []; - for (var i = 0; i < links.length; ++i) { - var linkElement = links.queryElementAt(i, Ci.nsIPropertyBag2); - // atom:link MUST have @href - if (bagHasKey(linkElement, "href")) { - var relAttribute = null; - if (bagHasKey(linkElement, "rel")) - relAttribute = linkElement.getPropertyAsAString("rel"); - if ((!relAttribute && rel == "alternate") || relAttribute == rel) { - rvLinks.push(linkElement); - continue; - } - // catch relations specified by IANA URI - if (relAttribute == IANA_URI + rel) { - rvLinks.push(linkElement); - } - } - } - return rvLinks; + var rvLinks = []; + for (var i = 0; i < links.length; ++i) { + var linkElement = links.queryElementAt(i, Ci.nsIPropertyBag2); + // atom:link MUST have @href + if (bagHasKey(linkElement, "href")) { + var relAttribute = null; + if (bagHasKey(linkElement, "rel")) + relAttribute = linkElement.getPropertyAsAString("rel"); + if ((!relAttribute && rel == "alternate") || relAttribute == rel) { + rvLinks.push(linkElement); + continue; + } + // catch relations specified by IANA URI + if (relAttribute == IANA_URI + rel) { + rvLinks.push(linkElement); + } + } + } + return rvLinks; } function xmlEscape(s) { - s = s.replace(/&/g, "&"); - s = s.replace(/>/g, ">"); - s = s.replace(//g, ">"); + s = s.replace(/ 0) { - ++entries_with_enclosures; + if (entry.enclosures && entry.enclosures.length > 0) { + ++entries_with_enclosures; - for (var e = 0; e < entry.enclosures.length; ++e) { - var enc = entry.enclosures.queryElementAt(e, Ci.nsIWritablePropertyBag2); - if (enc.hasKey("type")) { - var enctype = enc.get("type"); + for (var e = 0; e < entry.enclosures.length; ++e) { + var enc = entry.enclosures.queryElementAt(e, Ci.nsIWritablePropertyBag2); + if (enc.hasKey("type")) { + var enctype = enc.get("type"); - if (/^audio/.test(enctype)) { - ++audio_count; - } else if (/^image/.test(enctype)) { - ++image_count; - } else if (/^video/.test(enctype)) { - ++video_count; - } else { - ++other_count; - } - } else { - ++other_count; - } - } - } - } + if (/^audio/.test(enctype)) { + ++audio_count; + } else if (/^image/.test(enctype)) { + ++image_count; + } else if (/^video/.test(enctype)) { + ++video_count; + } else { + ++other_count; + } + } else { + ++other_count; + } + } + } + } - var feedtype = Ci.nsIFeed.TYPE_FEED; + var feedtype = Ci.nsIFeed.TYPE_FEED; - // For a feed to be marked as TYPE_VIDEO, TYPE_AUDIO and TYPE_IMAGE, - // we enforce two things: - // - // 1. all entries must have at least one enclosure - // 2. all enclosures must be video for TYPE_VIDEO, audio for TYPE_AUDIO or image - // for TYPE_IMAGE - // - // Otherwise it's a TYPE_FEED. - if (entries_with_enclosures == this.items.length && other_count == 0) { - if (audio_count > 0 && !video_count && !image_count) { - feedtype = Ci.nsIFeed.TYPE_AUDIO; + // For a feed to be marked as TYPE_VIDEO, TYPE_AUDIO and TYPE_IMAGE, + // we enforce two things: + // + // 1. all entries must have at least one enclosure + // 2. all enclosures must be video for TYPE_VIDEO, audio for TYPE_AUDIO or image + // for TYPE_IMAGE + // + // Otherwise it's a TYPE_FEED. + if (entries_with_enclosures == this.items.length && other_count == 0) { + if (audio_count > 0 && !video_count && !image_count) { + feedtype = Ci.nsIFeed.TYPE_AUDIO; - } else if (image_count > 0 && !audio_count && !video_count) { - feedtype = Ci.nsIFeed.TYPE_IMAGE; + } else if (image_count > 0 && !audio_count && !video_count) { + feedtype = Ci.nsIFeed.TYPE_IMAGE; - } else if (video_count > 0 && !audio_count && !image_count) { - feedtype = Ci.nsIFeed.TYPE_VIDEO; - } - } + } else if (video_count > 0 && !audio_count && !image_count) { + feedtype = Ci.nsIFeed.TYPE_VIDEO; + } + } - this.type = feedtype; - this.enclosureCount = other_count + video_count + audio_count + image_count; - }, + this.type = feedtype; + this.enclosureCount = other_count + video_count + audio_count + image_count; + }, - _atomLinksToURI: function Feed_linkToURI() { - var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray); - var alternates = findAtomLinks("alternate", links); - if (alternates.length > 0) { - var href = alternates[0].getPropertyAsAString("href"); - var base; - if (bagHasKey(alternates[0], "xml:base")) - base = alternates[0].getPropertyAsAString("xml:base"); - this.link = this._resolveURI(href, base); - } - }, + _atomLinksToURI: function Feed_linkToURI() { + var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray); + var alternates = findAtomLinks("alternate", links); + if (alternates.length > 0) { + var href = alternates[0].getPropertyAsAString("href"); + var base; + if (bagHasKey(alternates[0], "xml:base")) + base = alternates[0].getPropertyAsAString("xml:base"); + this.link = this._resolveURI(href, base); + } + }, - _resolveImageLink: function Feed_resolveImageLink() { - var base; - if (bagHasKey(this.image, "xml:base")) - base = this.image.getPropertyAsAString("xml:base"); - var url = this._resolveURI(this.image.getPropertyAsAString("url"), base); - if (url) - this.image.setPropertyAsAString("url", url.spec); - }, + _resolveImageLink: function Feed_resolveImageLink() { + var base; + if (bagHasKey(this.image, "xml:base")) + base = this.image.getPropertyAsAString("xml:base"); + var url = this._resolveURI(this.image.getPropertyAsAString("url"), base); + if (url) + this.image.setPropertyAsAString("url", url.spec); + }, - _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) { - var uri = null; - try { - var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI; - uri = strToURI(linkSpec, base); - } catch (e) { - LOG(e); - } + _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) { + var uri = null; + try { + var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI; + uri = strToURI(linkSpec, base); + } catch (e) { + LOG(e); + } - return uri; - }, + return uri; + }, - // reset the bag to raw contents, not text constructs - _resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) { - for (var i = 0; i < fieldLists.length; i++) { - for (var j = 0; j < fieldLists[i].length; j++) { - if (bagHasKey(this.fields, fieldLists[i][j])) { - var textConstruct = this.fields.getProperty(fieldLists[i][j]); - this.fields.setPropertyAsAString(fieldLists[i][j], - textConstruct.text); - } - } - } - }, + // reset the bag to raw contents, not text constructs + _resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) { + for (var i = 0; i < fieldLists.length; i++) { + for (var j = 0; j < fieldLists[i].length; j++) { + if (bagHasKey(this.fields, fieldLists[i][j])) { + var textConstruct = this.fields.getProperty(fieldLists[i][j]); + this.fields.setPropertyAsAString(fieldLists[i][j], + textConstruct.text); + } + } + } + }, - // XPCOM stuff - classID: FEED_CLASSID, - QueryInterface: ChromeUtils.generateQI([Ci.nsIFeed, Ci.nsIFeedContainer]), + // XPCOM stuff + classID: FEED_CLASSID, + QueryInterface: ChromeUtils.generateQI([Ci.nsIFeed, Ci.nsIFeedContainer]), }; function Entry() { - this.summary = null; - this.content = null; - this.title = null; - this.fields = Cc["@mozilla.org/hash-property-bag;1"]. - createInstance(Ci.nsIWritablePropertyBag2); - this.link = null; - this.id = null; - this.baseURI = null; - this.updated = null; - this.published = null; - this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); - this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); + this.summary = null; + this.content = null; + this.title = null; + this.fields = Cc["@mozilla.org/hash-property-bag;1"]. + createInstance(Ci.nsIWritablePropertyBag2); + this.link = null; + this.id = null; + this.baseURI = null; + this.updated = null; + this.published = null; + this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); + this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); } Entry.prototype = { - fields: null, - enclosures: null, - mediaContent: null, + fields: null, + enclosures: null, + mediaContent: null, - searchLists: { - title: ["title", "rss1:title", "atom03:title", "atom:title"], - link: [["link", strToURI], ["rss1:link", strToURI]], - id: [["guid", makePropGetter("guid")], "rdf:about", - "atom03:id", "atom:id"], - authors: ["authors"], - contributors: ["contributors"], - summary: ["description", "rss1:description", "dc:description", - "atom03:summary", "atom:summary"], - content: ["content:encoded", "atom03:content", "atom:content"], - rights: ["atom03:rights", "atom:rights"], - published: ["pubDate", "atom03:issued", "dcterms:issued", "atom:published"], - updated: ["pubDate", "atom03:modified", "dc:date", "dcterms:modified", - "atom:updated"], - }, + searchLists: { + title: ["title", "rss1:title", "atom03:title", "atom:title"], + link: [["link", strToURI], ["rss1:link", strToURI]], + id: [["guid", makePropGetter("guid")], "rdf:about", + "atom03:id", "atom:id"], + authors: ["authors"], + contributors: ["contributors"], + summary: ["description", "rss1:description", "dc:description", + "atom03:summary", "atom:summary"], + content: ["content:encoded", "atom03:content", "atom:content"], + rights: ["atom03:rights", "atom:rights"], + published: ["pubDate", "atom03:issued", "dcterms:issued", "atom:published"], + updated: ["pubDate", "atom03:modified", "dc:date", "dcterms:modified", + "atom:updated"], + }, - normalize: function Entry_normalize() { - fieldsToObj(this, this.searchLists); + normalize: function Entry_normalize() { + fieldsToObj(this, this.searchLists); - // Assign Atom link if needed - if (bagHasKey(this.fields, "links")) - this._atomLinksToURI(); + // Assign Atom link if needed + if (bagHasKey(this.fields, "links")) + this._atomLinksToURI(); - // Populate enclosures array - this._populateEnclosures(); + // Populate enclosures array + this._populateEnclosures(); - // The link might be a guid w/ permalink=true - if (!this.link && bagHasKey(this.fields, "guid")) { - var guid = this.fields.getProperty("guid"); - var isPermaLink = true; + // The link might be a guid w/ permalink=true + if (!this.link && bagHasKey(this.fields, "guid")) { + var guid = this.fields.getProperty("guid"); + var isPermaLink = true; - if (bagHasKey(guid, "isPermaLink")) - isPermaLink = guid.getProperty("isPermaLink").toLowerCase() != "false"; + if (bagHasKey(guid, "isPermaLink")) + isPermaLink = guid.getProperty("isPermaLink").toLowerCase() != "false"; - if (guid && isPermaLink) - this.link = strToURI(guid.getProperty("guid")); - } + if (guid && isPermaLink) + this.link = strToURI(guid.getProperty("guid")); + } - if (this.updated) - this.updated = dateParse(this.updated); - if (this.published) - this.published = dateParse(this.published); + if (this.updated) + this.updated = dateParse(this.updated); + if (this.published) + this.published = dateParse(this.published); - this._resetBagMembersToRawText([this.searchLists.content, - this.searchLists.summary, - this.searchLists.title]); - }, + this._resetBagMembersToRawText([this.searchLists.content, + this.searchLists.summary, + this.searchLists.title]); + }, - _populateEnclosures: function Entry_populateEnclosures() { - if (bagHasKey(this.fields, "links")) - this._atomLinksToEnclosures(); + _populateEnclosures: function Entry_populateEnclosures() { + if (bagHasKey(this.fields, "links")) + this._atomLinksToEnclosures(); - // Add RSS2 enclosure to enclosures - if (bagHasKey(this.fields, "enclosure")) - this._enclosureToEnclosures(); + // Add RSS2 enclosure to enclosures + if (bagHasKey(this.fields, "enclosure")) + this._enclosureToEnclosures(); - // Add media:content to enclosures - if (bagHasKey(this.fields, "mediacontent")) - this._mediaToEnclosures("mediacontent"); + // Add media:content to enclosures + if (bagHasKey(this.fields, "mediacontent")) + this._mediaToEnclosures("mediacontent"); - // Add media:thumbnail to enclosures - if (bagHasKey(this.fields, "mediathumbnail")) - this._mediaToEnclosures("mediathumbnail"); + // Add media:thumbnail to enclosures + if (bagHasKey(this.fields, "mediathumbnail")) + this._mediaToEnclosures("mediathumbnail"); - // Add media:content in media:group to enclosures - if (bagHasKey(this.fields, "mediagroup")) - this._mediaToEnclosures("mediagroup", "mediacontent"); - }, + // Add media:content in media:group to enclosures + if (bagHasKey(this.fields, "mediagroup")) + this._mediaToEnclosures("mediagroup", "mediacontent"); + }, - __enclosure_map: null, + __enclosure_map: null, - _addToEnclosures: function Entry_addToEnclosures(new_enc) { - // items we add to the enclosures array get displayed in the FeedWriter and - // they must have non-empty urls. - if (!bagHasKey(new_enc, "url") || new_enc.getPropertyAsAString("url") == "") - return; + _addToEnclosures: function Entry_addToEnclosures(new_enc) { + // items we add to the enclosures array get displayed in the FeedWriter and + // they must have non-empty urls. + if (!bagHasKey(new_enc, "url") || new_enc.getPropertyAsAString("url") == "") + return; - if (this.__enclosure_map == null) - this.__enclosure_map = {}; + if (this.__enclosure_map == null) + this.__enclosure_map = {}; - var previous_enc = this.__enclosure_map[new_enc.getPropertyAsAString("url")]; + var previous_enc = this.__enclosure_map[new_enc.getPropertyAsAString("url")]; - if (previous_enc != undefined) { - previous_enc.QueryInterface(Ci.nsIWritablePropertyBag2); + if (previous_enc != undefined) { + previous_enc.QueryInterface(Ci.nsIWritablePropertyBag2); - if (!bagHasKey(previous_enc, "type") && bagHasKey(new_enc, "type")) { - previous_enc.setPropertyAsAString("type", new_enc.getPropertyAsAString("type")); - try { - let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(new_enc.getPropertyAsAString("type"), null); - if (handlerInfoWrapper && handlerInfoWrapper.description) { - previous_enc.setPropertyAsAString("typeDesc", handlerInfoWrapper.description); - } - } catch (ext) {} - } + if (!bagHasKey(previous_enc, "type") && bagHasKey(new_enc, "type")) { + previous_enc.setPropertyAsAString("type", new_enc.getPropertyAsAString("type")); + try { + let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(new_enc.getPropertyAsAString("type"), null); + if (handlerInfoWrapper && handlerInfoWrapper.description) { + previous_enc.setPropertyAsAString("typeDesc", handlerInfoWrapper.description); + } + } catch (ext) {} + } - if (!bagHasKey(previous_enc, "length") && bagHasKey(new_enc, "length")) - previous_enc.setPropertyAsAString("length", new_enc.getPropertyAsAString("length")); + if (!bagHasKey(previous_enc, "length") && bagHasKey(new_enc, "length")) + previous_enc.setPropertyAsAString("length", new_enc.getPropertyAsAString("length")); - return; - } + return; + } - if (this.enclosures == null) { - this.enclosures = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); - this.enclosures.QueryInterface(Ci.nsIMutableArray); - } + if (this.enclosures == null) { + this.enclosures = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray); + this.enclosures.QueryInterface(Ci.nsIMutableArray); + } - this.enclosures.appendElement(new_enc); - this.__enclosure_map[new_enc.getPropertyAsAString("url")] = new_enc; - }, + this.enclosures.appendElement(new_enc); + this.__enclosure_map[new_enc.getPropertyAsAString("url")] = new_enc; + }, - _atomLinksToEnclosures: function Entry_linkToEnclosure() { - var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray); - var enc_links = findAtomLinks("enclosure", links); - if (enc_links.length == 0) - return; + _atomLinksToEnclosures: function Entry_linkToEnclosure() { + var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray); + var enc_links = findAtomLinks("enclosure", links); + if (enc_links.length == 0) + return; - for (var i = 0; i < enc_links.length; ++i) { - var link = enc_links[i]; + for (var i = 0; i < enc_links.length; ++i) { + var link = enc_links[i]; - // an enclosure must have an href - if (!(link.getProperty("href"))) - return; + // an enclosure must have an href + if (!(link.getProperty("href"))) + return; - var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); + var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); - // copy Atom bits over to equivalent enclosure bits - enc.setPropertyAsAString("url", link.getPropertyAsAString("href")); - if (bagHasKey(link, "type")) - enc.setPropertyAsAString("type", link.getPropertyAsAString("type")); - if (bagHasKey(link, "length")) - enc.setPropertyAsAString("length", link.getPropertyAsAString("length")); + // copy Atom bits over to equivalent enclosure bits + enc.setPropertyAsAString("url", link.getPropertyAsAString("href")); + if (bagHasKey(link, "type")) + enc.setPropertyAsAString("type", link.getPropertyAsAString("type")); + if (bagHasKey(link, "length")) + enc.setPropertyAsAString("length", link.getPropertyAsAString("length")); - this._addToEnclosures(enc); - } - }, + this._addToEnclosures(enc); + } + }, - _enclosureToEnclosures: function Entry_enclosureToEnclosures() { - var enc = this.fields.getPropertyAsInterface("enclosure", Ci.nsIPropertyBag2); + _enclosureToEnclosures: function Entry_enclosureToEnclosures() { + var enc = this.fields.getPropertyAsInterface("enclosure", Ci.nsIPropertyBag2); - if (!(enc.getProperty("url"))) - return; + if (!(enc.getProperty("url"))) + return; - this._addToEnclosures(enc); - }, + this._addToEnclosures(enc); + }, - _mediaToEnclosures: function Entry_mediaToEnclosures(mediaType, contentType) { - var content; + _mediaToEnclosures: function Entry_mediaToEnclosures(mediaType, contentType) { + var content; - // If a contentType is specified, the mediaType is a simple propertybag, - // and the contentType is an array inside it. - if (contentType) { - var group = this.fields.getPropertyAsInterface(mediaType, Ci.nsIPropertyBag2); - content = group.getPropertyAsInterface(contentType, Ci.nsIArray); - } else { - content = this.fields.getPropertyAsInterface(mediaType, Ci.nsIArray); - } + // If a contentType is specified, the mediaType is a simple propertybag, + // and the contentType is an array inside it. + if (contentType) { + var group = this.fields.getPropertyAsInterface(mediaType, Ci.nsIPropertyBag2); + content = group.getPropertyAsInterface(contentType, Ci.nsIArray); + } else { + content = this.fields.getPropertyAsInterface(mediaType, Ci.nsIArray); + } - for (var i = 0; i < content.length; ++i) { - var contentElement = content.queryElementAt(i, Ci.nsIWritablePropertyBag2); + for (var i = 0; i < content.length; ++i) { + var contentElement = content.queryElementAt(i, Ci.nsIWritablePropertyBag2); - // media:content don't require url, but if it's not there, we should - // skip it. - if (!bagHasKey(contentElement, "url")) - continue; + // media:content don't require url, but if it's not there, we should + // skip it. + if (!bagHasKey(contentElement, "url")) + continue; - var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); + var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); - // copy media:content bits over to equivalent enclosure bits - enc.setPropertyAsAString("url", contentElement.getPropertyAsAString("url")); - if (bagHasKey(contentElement, "type")) { - enc.setPropertyAsAString("type", contentElement.getPropertyAsAString("type")); - } else if (mediaType == "mediathumbnail") { - // thumbnails won't have a type, but default to image types - enc.setPropertyAsAString("type", "image/*"); - enc.setPropertyAsBool("thumbnail", true); - } + // copy media:content bits over to equivalent enclosure bits + enc.setPropertyAsAString("url", contentElement.getPropertyAsAString("url")); + if (bagHasKey(contentElement, "type")) { + enc.setPropertyAsAString("type", contentElement.getPropertyAsAString("type")); + } else if (mediaType == "mediathumbnail") { + // thumbnails won't have a type, but default to image types + enc.setPropertyAsAString("type", "image/*"); + enc.setPropertyAsBool("thumbnail", true); + } - if (bagHasKey(contentElement, "fileSize")) { - enc.setPropertyAsAString("length", contentElement.getPropertyAsAString("fileSize")); - } + if (bagHasKey(contentElement, "fileSize")) { + enc.setPropertyAsAString("length", contentElement.getPropertyAsAString("fileSize")); + } - this._addToEnclosures(enc); - } - }, + this._addToEnclosures(enc); + } + }, - // XPCOM stuff - classID: ENTRY_CLASSID, - QueryInterface: ChromeUtils.generateQI( - [Ci.nsIFeedEntry, Ci.nsIFeedContainer] - ), + // XPCOM stuff + classID: ENTRY_CLASSID, + QueryInterface: ChromeUtils.generateQI( + [Ci.nsIFeedEntry, Ci.nsIFeedContainer] + ), }; Entry.prototype._atomLinksToURI = Feed.prototype._atomLinksToURI; Entry.prototype._resolveURI = Feed.prototype._resolveURI; Entry.prototype._resetBagMembersToRawText = - Feed.prototype._resetBagMembersToRawText; + Feed.prototype._resetBagMembersToRawText; // TextConstruct represents and element that could contain (X)HTML function TextConstruct() { - this.lang = null; - this.base = null; - this.type = "text"; - this.text = null; - this.parserUtils = Cc[PARSERUTILS_CONTRACTID].getService(Ci.nsIParserUtils); + this.lang = null; + this.base = null; + this.type = "text"; + this.text = null; + this.parserUtils = Cc[PARSERUTILS_CONTRACTID].getService(Ci.nsIParserUtils); } TextConstruct.prototype = { - plainText: function TC_plainText() { - if (this.type != "text") { - return this.parserUtils.convertToPlainText(stripTags(this.text), - Ci.nsIDocumentEncoder.OutputSelectionOnly | - Ci.nsIDocumentEncoder.OutputAbsoluteLinks, - 0); - } - return this.text; - }, + plainText: function TC_plainText() { + if (this.type != "text") { + return this.parserUtils.convertToPlainText(stripTags(this.text), + Ci.nsIDocumentEncoder.OutputSelectionOnly | + Ci.nsIDocumentEncoder.OutputAbsoluteLinks, + 0); + } + return this.text; + }, - createDocumentFragment: function TC_createDocumentFragment(element) { - if (this.type == "text") { - var doc = element.ownerDocument; - var docFragment = doc.createDocumentFragment(); - var node = doc.createTextNode(this.text); - docFragment.appendChild(node); - return docFragment; - } - var isXML; - if (this.type == "xhtml") - isXML = true; - else if (this.type == "html") - isXML = false; - else - return null; + createDocumentFragment: function TC_createDocumentFragment(element) { + if (this.type == "text") { + var doc = element.ownerDocument; + var docFragment = doc.createDocumentFragment(); + var node = doc.createTextNode(this.text); + docFragment.appendChild(node); + return docFragment; + } + var isXML; + if (this.type == "xhtml") + isXML = true; + else if (this.type == "html") + isXML = false; + else + return null; - let flags = Ci.nsIParserUtils.SanitizerDropForms; - return this.parserUtils.parseFragment(this.text, flags, isXML, - this.base, element); - }, + let flags = Ci.nsIParserUtils.SanitizerDropForms; + return this.parserUtils.parseFragment(this.text, flags, isXML, + this.base, element); + }, - // XPCOM stuff - classID: TEXTCONSTRUCT_CLASSID, - QueryInterface: ChromeUtils.generateQI([Ci.nsIFeedTextConstruct]), + // XPCOM stuff + classID: TEXTCONSTRUCT_CLASSID, + QueryInterface: ChromeUtils.generateQI([Ci.nsIFeedTextConstruct]), }; // Generator represents the software that produced the feed function Generator() { - this.lang = null; - this.agent = null; - this.version = null; - this.uri = null; + this.lang = null; + this.agent = null; + this.version = null; + this.uri = null; - // nsIFeedElementBase - this._attributes = null; - this.baseURI = null; + // nsIFeedElementBase + this._attributes = null; + this.baseURI = null; } Generator.prototype = { - get attributes() { - return this._attributes; - }, + get attributes() { + return this._attributes; + }, - set attributes(value) { - this._attributes = value; - this.version = this._attributes.getValueFromName("", "version"); - var uriAttribute = this._attributes.getValueFromName("", "uri") || - this._attributes.getValueFromName("", "url"); - this.uri = strToURI(uriAttribute, this.baseURI); + set attributes(value) { + this._attributes = value; + this.version = this._attributes.getValueFromName("", "version"); + var uriAttribute = this._attributes.getValueFromName("", "uri") || + this._attributes.getValueFromName("", "url"); + this.uri = strToURI(uriAttribute, this.baseURI); - // RSS1 - uriAttribute = this._attributes.getValueFromName(RDF_NS, "resource"); - if (uriAttribute) { - this.agent = uriAttribute; - this.uri = strToURI(uriAttribute, this.baseURI); - } - }, + // RSS1 + uriAttribute = this._attributes.getValueFromName(RDF_NS, "resource"); + if (uriAttribute) { + this.agent = uriAttribute; + this.uri = strToURI(uriAttribute, this.baseURI); + } + }, - // XPCOM stuff - classID: GENERATOR_CLASSID, - QueryInterface: ChromeUtils.generateQI( - [Ci.nsIFeedGenerator, Ci.nsIFeedElementBase] - ), + // XPCOM stuff + classID: GENERATOR_CLASSID, + QueryInterface: ChromeUtils.generateQI( + [Ci.nsIFeedGenerator, Ci.nsIFeedElementBase] + ), }; function Person() { - this.name = null; - this.uri = null; - this.email = null; + this.name = null; + this.uri = null; + this.email = null; - // nsIFeedElementBase - this.attributes = null; - this.baseURI = null; + // nsIFeedElementBase + this.attributes = null; + this.baseURI = null; } Person.prototype = { - // XPCOM stuff - classID: PERSON_CLASSID, - QueryInterface: ChromeUtils.generateQI( - [Ci.nsIFeedPerson, Ci.nsIFeedElementBase] - ), + // XPCOM stuff + classID: PERSON_CLASSID, + QueryInterface: ChromeUtils.generateQI( + [Ci.nsIFeedPerson, Ci.nsIFeedElementBase] + ), }; /** @@ -704,23 +703,23 @@ Person.prototype = { * transformation function (like parseInt). */ function fieldsToObj(container, fields) { - var props, prop, field, searchList; - for (var key in fields) { - searchList = fields[key]; - for (var i = 0; i < searchList.length; ++i) { - props = searchList[i]; - prop = null; - field = isArray(props) ? props[0] : props; - try { - prop = container.fields.getProperty(field); - } catch (e) { - } - if (prop) { - prop = isArray(props) ? props[1](prop) : prop; - container[key] = prop; - } - } - } + var props, prop, field, searchList; + for (var key in fields) { + searchList = fields[key]; + for (var i = 0; i < searchList.length; ++i) { + props = searchList[i]; + prop = null; + field = isArray(props) ? props[0] : props; + try { + prop = container.fields.getProperty(field); + } catch (e) { + } + if (prop) { + prop = isArray(props) ? props[1](prop) : prop; + container[key] = prop; + } + } + } } /** @@ -730,33 +729,33 @@ function fieldsToObj(container, fields) { * @returns The lower case localName property of the specified element */ function LC(element) { - return element.localName.toLowerCase(); + return element.localName.toLowerCase(); } // TODO move these post-processor functions // create a generator element function atomGenerator(s, generator) { - generator.QueryInterface(Ci.nsIFeedGenerator); - generator.agent = s.trim(); - return generator; + generator.QueryInterface(Ci.nsIFeedGenerator); + generator.agent = s.trim(); + return generator; } // post-process atom:logo to create an RSS2-like structure function atomLogo(s, logo) { - logo.setPropertyAsAString("url", s.trim()); + logo.setPropertyAsAString("url", s.trim()); } // post-process an RSS category, map it to the Atom fields. function rssCatTerm(s, cat) { - // add slash handling? - cat.setPropertyAsAString("term", s.trim()); - return cat; + // add slash handling? + cat.setPropertyAsAString("term", s.trim()); + return cat; } // post-process a GUID function rssGuid(s, guid) { - guid.setPropertyAsAString("guid", s.trim()); - return guid; + guid.setPropertyAsAString("guid", s.trim()); + return guid; } // post-process an RSS author element @@ -773,33 +772,33 @@ function rssGuid(s, guid) { // fields. // function rssAuthor(s, author) { - author.QueryInterface(Ci.nsIFeedPerson); - // check for RSS2 string format - var chars = s.trim(); - var matches = chars.match(/(.*)\((.*)\)/); - var emailCheck = - /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; - if (matches) { - var match1 = matches[1].trim(); - var match2 = matches[2].trim(); - if (match2.indexOf("mailto:") == 0) - match2 = match2.substring(7); - if (emailCheck.test(match1)) { - author.email = match1; - author.name = match2; - } else if (emailCheck.test(match2)) { - author.email = match2; - author.name = match1; - } else { - // put it back together - author.name = match1 + " (" + match2 + ")"; - } - } else { - author.name = chars; - if (chars.indexOf("@")) - author.email = chars; - } - return author; + author.QueryInterface(Ci.nsIFeedPerson); + // check for RSS2 string format + var chars = s.trim(); + var matches = chars.match(/(.*)\((.*)\)/); + var emailCheck = + /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; + if (matches) { + var match1 = matches[1].trim(); + var match2 = matches[2].trim(); + if (match2.indexOf("mailto:") == 0) + match2 = match2.substring(7); + if (emailCheck.test(match1)) { + author.email = match1; + author.name = match2; + } else if (emailCheck.test(match2)) { + author.email = match2; + author.name = match1; + } else { + // put it back together + author.name = match1 + " (" + match2 + ")"; + } + } else { + author.name = chars; + if (chars.indexOf("@")) + author.email = chars; + } + return author; } // @@ -807,11 +806,11 @@ function rssAuthor(s, author) { // 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; + var str = Cc["@mozilla.org/supports-string;1"]. + createInstance(Ci.nsISupportsString); + str.data = s; + str.QueryInterface(Ci.nsISupportsString); + return str; } /** @@ -821,117 +820,117 @@ function rssArrayElement(s) { * @return A Date.toUTCString, or null if the string can't be parsed. */ function dateParse(aDateString) { - let dateString = aDateString.trim(); - // Without bug 682781 fixed, JS won't parse an RFC822 date with a Z for the - // timezone, so convert to -00:00 which works for any date format. - dateString = dateString.replace(/z$/i, "-00:00"); - let date = new Date(dateString); - if (!isNaN(date)) { - return date.toUTCString(); - } - return null; + let dateString = aDateString.trim(); + // Without bug 682781 fixed, JS won't parse an RFC822 date with a Z for the + // timezone, so convert to -00:00 which works for any date format. + dateString = dateString.replace(/z$/i, "-00:00"); + let date = new Date(dateString); + if (!isNaN(date)) { + return date.toUTCString(); + } + return null; } const XHTML_NS = "http://www.w3.org/1999/xhtml"; // The XHTMLHandler handles inline XHTML found in things like atom:summary function XHTMLHandler(processor, isAtom) { - this._buf = ""; - this._processor = processor; - this._depth = 0; - this._isAtom = isAtom; - // a stack of lists tracking in-scope namespaces - this._inScopeNS = []; + this._buf = ""; + this._processor = processor; + this._depth = 0; + this._isAtom = isAtom; + // a stack of lists tracking in-scope namespaces + this._inScopeNS = []; } // The fidelity can be improved here, to allow handling of stuff like // SVG and MathML. XXX XHTMLHandler.prototype = { - // look back up at the declared namespaces - // we always use the same prefixes for our safe stuff - _isInScope: function XH__isInScope(ns) { - for (var i in this._inScopeNS) { - for (var uri in this._inScopeNS[i]) { - if (this._inScopeNS[i][uri] == ns) - return true; - } - } - return false; - }, + // look back up at the declared namespaces + // we always use the same prefixes for our safe stuff + _isInScope: function XH__isInScope(ns) { + for (var i in this._inScopeNS) { + for (var uri in this._inScopeNS[i]) { + if (this._inScopeNS[i][uri] == ns) + return true; + } + } + return false; + }, - startDocument: function XH_startDocument() { - }, - endDocument: function XH_endDocument() { - }, - startElement: function XH_startElement(namespace, localName, qName, attributes) { - ++this._depth; - this._inScopeNS.push([]); + startDocument: function XH_startDocument() { + }, + endDocument: function XH_endDocument() { + }, + startElement: function XH_startElement(namespace, localName, qName, attributes) { + ++this._depth; + this._inScopeNS.push([]); - // RFC4287 requires XHTML to be wrapped in a div that is *not* part of - // the content. This prevents people from screwing up namespaces, but - // we need to skip it here. - if (this._isAtom && this._depth == 1 && localName == "div") - return; + // RFC4287 requires XHTML to be wrapped in a div that is *not* part of + // the content. This prevents people from screwing up namespaces, but + // we need to skip it here. + if (this._isAtom && this._depth == 1 && localName == "div") + return; - // If it's an XHTML element, record it. Otherwise, it's ignored. - if (namespace == XHTML_NS) { - this._buf += "<" + localName; - var uri; - for (var i = 0; i < attributes.length; ++i) { - uri = attributes.getURI(i); - // XHTML attributes aren't in a namespace - if (uri == "") { - this._buf += (" " + attributes.getLocalName(i) + "='" + - xmlEscape(attributes.getValue(i)) + "'"); - } else { - // write a small set of allowed attribute namespaces - var prefix = gAllowedXHTMLNamespaces[uri]; - if (prefix != null) { - // The attribute value we'll attempt to write - var attributeValue = xmlEscape(attributes.getValue(i)); + // If it's an XHTML element, record it. Otherwise, it's ignored. + if (namespace == XHTML_NS) { + this._buf += "<" + localName; + var uri; + for (var i = 0; i < attributes.length; ++i) { + uri = attributes.getURI(i); + // XHTML attributes aren't in a namespace + if (uri == "") { + this._buf += (" " + attributes.getLocalName(i) + "='" + + xmlEscape(attributes.getValue(i)) + "'"); + } else { + // write a small set of allowed attribute namespaces + var prefix = gAllowedXHTMLNamespaces[uri]; + if (prefix != null) { + // The attribute value we'll attempt to write + var attributeValue = xmlEscape(attributes.getValue(i)); - // it's an allowed attribute NS. - // write the attribute - this._buf += (" " + prefix + ":" + - attributes.getLocalName(i) + - "='" + attributeValue + "'"); + // it's an allowed attribute NS. + // write the attribute + this._buf += (" " + prefix + ":" + + attributes.getLocalName(i) + + "='" + attributeValue + "'"); - // write an xmlns declaration if necessary - if (prefix != "xml" && !this._isInScope(uri)) { - this._inScopeNS[this._inScopeNS.length - 1].push(uri); - this._buf += " xmlns:" + prefix + "='" + uri + "'"; - } - } - } - } - this._buf += ">"; - } - }, - endElement: function XH_endElement(uri, localName, qName) { - --this._depth; - this._inScopeNS.pop(); + // write an xmlns declaration if necessary + if (prefix != "xml" && !this._isInScope(uri)) { + this._inScopeNS[this._inScopeNS.length - 1].push(uri); + this._buf += " xmlns:" + prefix + "='" + uri + "'"; + } + } + } + } + this._buf += ">"; + } + }, + endElement: function XH_endElement(uri, localName, qName) { + --this._depth; + this._inScopeNS.pop(); - // We need to skip outer divs in Atom. See comment in startElement. - if (this._isAtom && this._depth == 0 && localName == "div") - return; + // We need to skip outer divs in Atom. See comment in startElement. + if (this._isAtom && this._depth == 0 && localName == "div") + return; - // When we peek too far, go back to the main processor - if (this._depth < 0) { - this._processor.returnFromXHTMLHandler(this._buf.trim(), - uri, localName, qName); - return; - } - // If it's an XHTML element, record it. Otherwise, it's ignored. - if (uri == XHTML_NS) { - this._buf += ""; - } - }, - characters: function XH_characters(data) { - this._buf += xmlEscape(data); - }, - processingInstruction: function XH_processingInstruction() { - }, + // When we peek too far, go back to the main processor + if (this._depth < 0) { + this._processor.returnFromXHTMLHandler(this._buf.trim(), + uri, localName, qName); + return; + } + // If it's an XHTML element, record it. Otherwise, it's ignored. + if (uri == XHTML_NS) { + this._buf += ""; + } + }, + characters: function XH_characters(data) { + this._buf += xmlEscape(data); + }, + processingInstruction: function XH_processingInstruction() { + }, }; /** @@ -939,53 +938,53 @@ XHTMLHandler.prototype = { * added to our transition table in the FeedProcessor. */ function ExtensionHandler(processor) { - this._buf = ""; - this._depth = 0; - this._hasChildElements = false; + this._buf = ""; + this._depth = 0; + this._hasChildElements = false; - // The FeedProcessor - this._processor = processor; + // The FeedProcessor + this._processor = processor; - // Fields of the outermost extension element. - this._localName = null; - this._uri = null; - this._qName = null; - this._attrs = null; + // Fields of the outermost extension element. + this._localName = null; + this._uri = null; + this._qName = null; + this._attrs = null; } ExtensionHandler.prototype = { - startDocument: function EH_startDocument() { - }, - endDocument: function EH_endDocument() { - }, - startElement: function EH_startElement(uri, localName, qName, attrs) { - ++this._depth; + startDocument: function EH_startDocument() { + }, + endDocument: function EH_endDocument() { + }, + startElement: function EH_startElement(uri, localName, qName, attrs) { + ++this._depth; - if (this._depth == 1) { - this._uri = uri; - this._localName = localName; - this._qName = qName; - this._attrs = attrs; - } + if (this._depth == 1) { + this._uri = uri; + this._localName = localName; + this._qName = qName; + this._attrs = attrs; + } - // if we descend into another element, we won't send text - this._hasChildElements = (this._depth > 1); + // if we descend into another element, we won't send text + this._hasChildElements = (this._depth > 1); - }, - endElement: function EH_endElement(uri, localName, qName) { - --this._depth; - if (this._depth == 0) { - var text = this._hasChildElements ? null : this._buf.trim(); - this._processor.returnFromExtHandler(this._uri, this._localName, - text, this._attrs); - } - }, - characters: function EH_characters(data) { - if (!this._hasChildElements) - this._buf += data; - }, - processingInstruction: function EH_processingInstruction() { - }, + }, + endElement: function EH_endElement(uri, localName, qName) { + --this._depth; + if (this._depth == 0) { + var text = this._hasChildElements ? null : this._buf.trim(); + this._processor.returnFromExtHandler(this._uri, this._localName, + text, this._attrs); + } + }, + characters: function EH_characters(data) { + if (!this._hasChildElements) + this._buf += data; + }, + processingInstruction: function EH_processingInstruction() { + }, }; @@ -996,20 +995,20 @@ ExtensionHandler.prototype = { * than once inside a given entry or feed. */ function ElementInfo(fieldName, containerClass, closeFunc, isArray) { - this.fieldName = fieldName; - this.containerClass = containerClass; - this.closeFunc = closeFunc; - this.isArray = isArray; - this.isWrapper = false; + this.fieldName = fieldName; + this.containerClass = containerClass; + this.closeFunc = closeFunc; + this.isArray = isArray; + this.isWrapper = false; } /** * FeedElementInfo represents a feed element, usually the root. */ function FeedElementInfo(fieldName, feedVersion) { - this.isWrapper = false; - this.fieldName = fieldName; - this.feedVersion = feedVersion; + this.isWrapper = false; + this.fieldName = fieldName; + this.feedVersion = feedVersion; } /** @@ -1018,718 +1017,718 @@ function FeedElementInfo(fieldName, feedVersion) { * of during parsing. */ function WrapperElementInfo(fieldName) { - this.isWrapper = true; - this.fieldName = fieldName; + this.isWrapper = true; + this.fieldName = fieldName; } /** *** The Processor *****/ function FeedProcessor() { - this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader); - this._buf = ""; - this._feed = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); - this._handlerStack = []; - this._xmlBaseStack = []; // sparse array keyed to nesting depth - this._depth = 0; - this._state = "START"; - this._result = null; - this._extensionHandler = null; - this._xhtmlHandler = null; - this._haveSentResult = false; + this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader); + this._buf = ""; + this._feed = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); + this._handlerStack = []; + this._xmlBaseStack = []; // sparse array keyed to nesting depth + this._depth = 0; + this._state = "START"; + this._result = null; + this._extensionHandler = null; + this._xhtmlHandler = null; + this._haveSentResult = false; - // The nsIFeedResultListener waiting for the parse results - this.listener = null; + // The nsIFeedResultListener waiting for the parse results + this.listener = null; - // These elements can contain (X)HTML or plain text. - // We keep a table here that contains their default treatment - this._textConstructs = {"atom:title": "text", - "atom:summary": "text", - "atom:rights": "text", - "atom:content": "text", - "atom:subtitle": "text", - "description": "html", - "rss1:description": "html", - "dc:description": "html", - "content:encoded": "html", - "title": "text", - "rss1:title": "text", - "atom03:title": "text", - "atom03:tagline": "text", - "atom03:summary": "text", - "atom03:content": "text"}; - this._stack = []; + // These elements can contain (X)HTML or plain text. + // We keep a table here that contains their default treatment + this._textConstructs = {"atom:title": "text", + "atom:summary": "text", + "atom:rights": "text", + "atom:content": "text", + "atom:subtitle": "text", + "description": "html", + "rss1:description": "html", + "dc:description": "html", + "content:encoded": "html", + "title": "text", + "rss1:title": "text", + "atom03:title": "text", + "atom03:tagline": "text", + "atom03:summary": "text", + "atom03:content": "text"}; + this._stack = []; - this._trans = { - "START": { - // If we hit a root RSS element, treat as RSS2. - "rss": new FeedElementInfo("RSS2", "rss2"), + this._trans = { + "START": { + // If we hit a root RSS element, treat as RSS2. + "rss": new FeedElementInfo("RSS2", "rss2"), - // If we hit an RDF element, if could be RSS1, but we can't - // verify that until we hit a rss1:channel element. - "rdf:RDF": new WrapperElementInfo("RDF"), + // If we hit an RDF element, if could be RSS1, but we can't + // verify that until we hit a rss1:channel element. + "rdf:RDF": new WrapperElementInfo("RDF"), - // If we hit a Atom 1.0 element, treat as Atom 1.0. - "atom:feed": new FeedElementInfo("Atom", "atom"), + // If we hit a Atom 1.0 element, treat as Atom 1.0. + "atom:feed": new FeedElementInfo("Atom", "atom"), - // Treat as Atom 0.3 - "atom03:feed": new FeedElementInfo("Atom03", "atom03"), - }, + // Treat as Atom 0.3 + "atom03:feed": new FeedElementInfo("Atom03", "atom03"), + }, - /** ******* RSS2 **********/ - "IN_RSS2": { - "channel": new WrapperElementInfo("channel"), - }, + /** ******* RSS2 **********/ + "IN_RSS2": { + "channel": new WrapperElementInfo("channel"), + }, - "IN_CHANNEL": { - "item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true), - "managingEditor": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "category": new ElementInfo("categories", null, rssCatTerm, true), - "cloud": new ElementInfo("cloud", null, null, false), - "image": new ElementInfo("image", null, null, false), - "textInput": new ElementInfo("textInput", null, null, false), - "skipDays": new ElementInfo("skipDays", null, null, false), - "skipHours": new ElementInfo("skipHours", null, null, false), - "generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], - atomGenerator, false), - }, + "IN_CHANNEL": { + "item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true), + "managingEditor": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "category": new ElementInfo("categories", null, rssCatTerm, true), + "cloud": new ElementInfo("cloud", null, null, false), + "image": new ElementInfo("image", null, null, false), + "textInput": new ElementInfo("textInput", null, null, false), + "skipDays": new ElementInfo("skipDays", null, null, false), + "skipHours": new ElementInfo("skipHours", null, null, false), + "generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], + atomGenerator, false), + }, - "IN_ITEMS": { - "author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "category": new ElementInfo("categories", null, rssCatTerm, true), - "enclosure": new ElementInfo("enclosure", null, null, false), - "media:content": new ElementInfo("mediacontent", null, null, true), - "media:group": new ElementInfo("mediagroup", null, null, false), - "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true), - "guid": new ElementInfo("guid", null, rssGuid, false), - }, + "IN_ITEMS": { + "author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "category": new ElementInfo("categories", null, rssCatTerm, true), + "enclosure": new ElementInfo("enclosure", null, null, false), + "media:content": new ElementInfo("mediacontent", null, null, true), + "media:group": new ElementInfo("mediagroup", null, null, false), + "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true), + "guid": new ElementInfo("guid", null, rssGuid, false), + }, - "IN_SKIPDAYS": { - "day": new ElementInfo("days", null, rssArrayElement, true), - }, + "IN_SKIPDAYS": { + "day": new ElementInfo("days", null, rssArrayElement, true), + }, - "IN_SKIPHOURS": { - "hour": new ElementInfo("hours", null, rssArrayElement, true), - }, + "IN_SKIPHOURS": { + "hour": new ElementInfo("hours", null, rssArrayElement, true), + }, - "IN_MEDIAGROUP": { - "media:content": new ElementInfo("mediacontent", null, null, true), - "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true), - }, + "IN_MEDIAGROUP": { + "media:content": new ElementInfo("mediacontent", null, null, true), + "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true), + }, - /** ******* RSS1 **********/ - "IN_RDF": { - // If we hit a rss1:channel, we can verify that we have RSS1 - "rss1:channel": new FeedElementInfo("rdf_channel", "rss1"), - "rss1:image": new ElementInfo("image", null, null, false), - "rss1:textinput": new ElementInfo("textInput", null, null, false), - "rss1:item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true), - }, + /** ******* RSS1 **********/ + "IN_RDF": { + // If we hit a rss1:channel, we can verify that we have RSS1 + "rss1:channel": new FeedElementInfo("rdf_channel", "rss1"), + "rss1:image": new ElementInfo("image", null, null, false), + "rss1:textinput": new ElementInfo("textInput", null, null, false), + "rss1:item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true), + }, - "IN_RDF_CHANNEL": { - "admin:generatorAgent": new ElementInfo("generator", - Cc[GENERATOR_CONTRACTID], - null, false), - "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], - rssAuthor, true), - }, + "IN_RDF_CHANNEL": { + "admin:generatorAgent": new ElementInfo("generator", + Cc[GENERATOR_CONTRACTID], + null, false), + "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], + rssAuthor, true), + }, - /** ******* ATOM 1.0 **********/ - "IN_ATOM": { - "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - null, true), - "atom:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], - atomGenerator, false), - "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], - null, true), - "atom:link": new ElementInfo("links", null, null, true), - "atom:logo": new ElementInfo("atom:logo", null, atomLogo, false), - "atom:entry": new ElementInfo("entries", Cc[ENTRY_CONTRACTID], - null, true), - }, + /** ******* ATOM 1.0 **********/ + "IN_ATOM": { + "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + null, true), + "atom:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], + atomGenerator, false), + "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], + null, true), + "atom:link": new ElementInfo("links", null, null, true), + "atom:logo": new ElementInfo("atom:logo", null, atomLogo, false), + "atom:entry": new ElementInfo("entries", Cc[ENTRY_CONTRACTID], + null, true), + }, - "IN_ENTRIES": { - "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - null, true), - "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], - null, true), - "atom:link": new ElementInfo("links", null, null, true), - }, + "IN_ENTRIES": { + "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + null, true), + "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID], + null, true), + "atom:link": new ElementInfo("links", null, null, true), + }, - /** ******* ATOM 0.3 **********/ - "IN_ATOM03": { - "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - null, true), - "atom03:contributor": new ElementInfo("contributors", - Cc[PERSON_CONTRACTID], - null, true), - "atom03:link": new ElementInfo("links", null, null, true), - "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID], - null, true), - "atom03:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], - atomGenerator, false), - }, + /** ******* ATOM 0.3 **********/ + "IN_ATOM03": { + "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + null, true), + "atom03:contributor": new ElementInfo("contributors", + Cc[PERSON_CONTRACTID], + null, true), + "atom03:link": new ElementInfo("links", null, null, true), + "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID], + null, true), + "atom03:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID], + atomGenerator, false), + }, - "IN_ATOM03_ENTRIES": { - "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], - null, true), - "atom03:contributor": new ElementInfo("contributors", - Cc[PERSON_CONTRACTID], - null, true), - "atom03:link": new ElementInfo("links", null, null, true), - "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID], - null, true), - }, - }; + "IN_ATOM03_ENTRIES": { + "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID], + null, true), + "atom03:contributor": new ElementInfo("contributors", + Cc[PERSON_CONTRACTID], + null, true), + "atom03:link": new ElementInfo("links", null, null, true), + "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID], + null, true), + }, + }; } // See startElement for a long description of how feeds are processed. FeedProcessor.prototype = { - // Set ourselves as the SAX handler, and set the base URI - _init: function FP_init(uri) { - this._reader.contentHandler = this; - this._reader.errorHandler = this; - this._result = Cc[FR_CONTRACTID].createInstance(Ci.nsIFeedResult); - if (uri) { - this._result.uri = uri; - this._reader.baseURI = uri; - this._xmlBaseStack[0] = uri; - } - }, + // Set ourselves as the SAX handler, and set the base URI + _init: function FP_init(uri) { + this._reader.contentHandler = this; + this._reader.errorHandler = this; + this._result = Cc[FR_CONTRACTID].createInstance(Ci.nsIFeedResult); + if (uri) { + this._result.uri = uri; + this._reader.baseURI = uri; + this._xmlBaseStack[0] = uri; + } + }, - // This function is called once we figure out what type of feed - // we're dealing with. Some feed types require digging a bit further - // than the root. - _docVerified: function FP_docVerified(version) { - this._result.doc = Cc[FEED_CONTRACTID].createInstance(Ci.nsIFeed); - this._result.doc.baseURI = - this._xmlBaseStack[this._xmlBaseStack.length - 1]; - this._result.doc.fields = this._feed; - this._result.version = version; - }, + // This function is called once we figure out what type of feed + // we're dealing with. Some feed types require digging a bit further + // than the root. + _docVerified: function FP_docVerified(version) { + this._result.doc = Cc[FEED_CONTRACTID].createInstance(Ci.nsIFeed); + this._result.doc.baseURI = + this._xmlBaseStack[this._xmlBaseStack.length - 1]; + this._result.doc.fields = this._feed; + this._result.version = version; + }, - // When we're done with the feed, let the listener know what - // happened. - _sendResult: function FP_sendResult() { - this._haveSentResult = true; - try { - // Can be null when a non-feed is fed to us - if (this._result.doc) - this._result.doc.normalize(); - } catch (e) { - LOG("FIXME: " + e); - } + // When we're done with the feed, let the listener know what + // happened. + _sendResult: function FP_sendResult() { + this._haveSentResult = true; + try { + // Can be null when a non-feed is fed to us + if (this._result.doc) + this._result.doc.normalize(); + } catch (e) { + LOG("FIXME: " + e); + } - try { - if (this.listener != null) - this.listener.handleResult(this._result); - } finally { - this._result = null; - } - }, + try { + if (this.listener != null) + this.listener.handleResult(this._result); + } finally { + this._result = null; + } + }, - // Parsing functions - parseAsync: function FP_parseAsync(requestObserver, uri) { - this._init(uri); - this._reader.parseAsync(requestObserver); - }, + // Parsing functions + parseAsync: function FP_parseAsync(requestObserver, uri) { + this._init(uri); + this._reader.parseAsync(requestObserver); + }, - // nsIStreamListener + // nsIStreamListener - // The XMLReader will throw sensible exceptions if these get called - // out of order. - onStartRequest: function FP_onStartRequest(request, context) { - // this will throw if the request is not a channel, but so will nsParser. - var channel = request.QueryInterface(Ci.nsIChannel); - channel.contentType = "application/vnd.mozilla.maybe.feed"; - this._reader.onStartRequest(request, context); - }, + // The XMLReader will throw sensible exceptions if these get called + // out of order. + onStartRequest: function FP_onStartRequest(request, context) { + // this will throw if the request is not a channel, but so will nsParser. + var channel = request.QueryInterface(Ci.nsIChannel); + channel.contentType = "application/vnd.mozilla.maybe.feed"; + this._reader.onStartRequest(request, context); + }, - onStopRequest: function FP_onStopRequest(request, context, statusCode) { - try { - this._reader.onStopRequest(request, context, statusCode); - } finally { - this._reader = null; - } - }, + onStopRequest: function FP_onStopRequest(request, context, statusCode) { + try { + this._reader.onStopRequest(request, context, statusCode); + } finally { + this._reader = null; + } + }, - onDataAvailable: - function FP_onDataAvailable(request, context, inputStream, offset, count) { - this._reader.onDataAvailable(request, context, inputStream, offset, count); - }, + onDataAvailable: + function FP_onDataAvailable(request, context, inputStream, offset, count) { + this._reader.onDataAvailable(request, context, inputStream, offset, count); + }, - // nsISAXErrorHandler + // nsISAXErrorHandler - // We only care about fatal errors. When this happens, we may have - // parsed through the feed metadata and some number of entries. The - // listener can still show some of that data if it wants, and we'll - // set the bozo bit to indicate we were unable to parse all the way - // through. - fatalError: function FP_reportError() { - this._result.bozo = true; - // XXX need to QI to FeedProgressListener - if (!this._haveSentResult) - this._sendResult(); - }, + // We only care about fatal errors. When this happens, we may have + // parsed through the feed metadata and some number of entries. The + // listener can still show some of that data if it wants, and we'll + // set the bozo bit to indicate we were unable to parse all the way + // through. + fatalError: function FP_reportError() { + this._result.bozo = true; + // XXX need to QI to FeedProgressListener + if (!this._haveSentResult) + this._sendResult(); + }, - // nsISAXContentHandler + // nsISAXContentHandler - startDocument: function FP_startDocument() { - // LOG("----------"); - }, + startDocument: function FP_startDocument() { + // LOG("----------"); + }, - endDocument: function FP_endDocument() { - if (!this._haveSentResult) - this._sendResult(); - }, + endDocument: function FP_endDocument() { + if (!this._haveSentResult) + this._sendResult(); + }, - // The transitions defined above identify elements that contain more - // than just text. For example RSS items contain many fields, and so - // do Atom authors. The only commonly used elements that contain - // mixed content are Atom Text Constructs of type="xhtml", which we - // delegate to another handler for cleaning. That leaves a couple - // different types of elements to deal with: those that should occur - // only once, such as title elements, and those that can occur - // multiple times, such as the RSS category element and the Atom - // link element. Most of the RSS1/DC elements can occur multiple - // times in theory, but in practice, the only ones that do have - // analogues in Atom. - // - // Some elements are also groups of attributes or sub-elements, - // while others are simple text fields. For the most part, we don't - // have to pay explicit attention to the simple text elements, - // unless we want to post-process the resulting string to transform - // it into some richer object like a Date or URI. - // - // Elements that have more sophisticated content models still end up - // being dictionaries, whether they are based on attributes like RSS - // cloud, sub-elements like Atom author, or even items and - // entries. These elements are treated as "containers". It's - // theoretically possible for a container to have an attribute with - // the same universal name as a sub-element, but none of the feed - // formats allow this by default, and I don't of any extension that - // works this way. - // - startElement: function FP_startElement(uri, localName, qName, attributes) { - this._buf = ""; - ++this._depth; - var elementInfo; + // The transitions defined above identify elements that contain more + // than just text. For example RSS items contain many fields, and so + // do Atom authors. The only commonly used elements that contain + // mixed content are Atom Text Constructs of type="xhtml", which we + // delegate to another handler for cleaning. That leaves a couple + // different types of elements to deal with: those that should occur + // only once, such as title elements, and those that can occur + // multiple times, such as the RSS category element and the Atom + // link element. Most of the RSS1/DC elements can occur multiple + // times in theory, but in practice, the only ones that do have + // analogues in Atom. + // + // Some elements are also groups of attributes or sub-elements, + // while others are simple text fields. For the most part, we don't + // have to pay explicit attention to the simple text elements, + // unless we want to post-process the resulting string to transform + // it into some richer object like a Date or URI. + // + // Elements that have more sophisticated content models still end up + // being dictionaries, whether they are based on attributes like RSS + // cloud, sub-elements like Atom author, or even items and + // entries. These elements are treated as "containers". It's + // theoretically possible for a container to have an attribute with + // the same universal name as a sub-element, but none of the feed + // formats allow this by default, and I don't of any extension that + // works this way. + // + startElement: function FP_startElement(uri, localName, qName, attributes) { + this._buf = ""; + ++this._depth; + var elementInfo; - // LOG("<" + localName + ">"); + // LOG("<" + localName + ">"); - // Check for xml:base - var base = attributes.getValueFromName(XMLNS, "base"); - if (base) { - this._xmlBaseStack[this._depth] = - strToURI(base, this._xmlBaseStack[this._xmlBaseStack.length - 1]); - } + // Check for xml:base + var base = attributes.getValueFromName(XMLNS, "base"); + if (base) { + this._xmlBaseStack[this._depth] = + strToURI(base, this._xmlBaseStack[this._xmlBaseStack.length - 1]); + } - // To identify the element we're dealing with, we look up the - // namespace URI in our gNamespaces dictionary, which will give us - // a "canonical" prefix for a namespace URI. For example, this - // allows Dublin Core "creator" elements to be consistently mapped - // to "dc:creator", for easy field access by consumer code. This - // strategy also happens to shorten up our state table. - var key = this._prefixForNS(uri) + localName; + // To identify the element we're dealing with, we look up the + // namespace URI in our gNamespaces dictionary, which will give us + // a "canonical" prefix for a namespace URI. For example, this + // allows Dublin Core "creator" elements to be consistently mapped + // to "dc:creator", for easy field access by consumer code. This + // strategy also happens to shorten up our state table. + var key = this._prefixForNS(uri) + localName; - // Check to see if we need to hand this off to our XHTML handler. - // The elements we're dealing with will look like this: - // - // - // <div xmlns="http://www.w3.org/1999/xhtml"> - // A title with <b>bold</b> and <i>italics</i>. - // </div> - // - // - // When it returns in returnFromXHTMLHandler, the handler should - // give us back a string like this: - // - // "A title with bold and italics." - // - // The Atom spec explicitly says the div is not part of the content, - // and explicitly allows whitespace collapsing. - // - if ((this._result.version == "atom" || this._result.version == "atom03") && - this._textConstructs[key] != null) { - var type = attributes.getValueFromName("", "type"); - if (type != null && type.includes("xhtml")) { - this._xhtmlHandler = - new XHTMLHandler(this, (this._result.version == "atom")); - this._reader.contentHandler = this._xhtmlHandler; - return; - } - } + // Check to see if we need to hand this off to our XHTML handler. + // The elements we're dealing with will look like this: + // + // + // <div xmlns="http://www.w3.org/1999/xhtml"> + // A title with <b>bold</b> and <i>italics</i>. + // </div> + // + // + // When it returns in returnFromXHTMLHandler, the handler should + // give us back a string like this: + // + // "A title with bold and italics." + // + // The Atom spec explicitly says the div is not part of the content, + // and explicitly allows whitespace collapsing. + // + if ((this._result.version == "atom" || this._result.version == "atom03") && + this._textConstructs[key] != null) { + var type = attributes.getValueFromName("", "type"); + if (type != null && type.includes("xhtml")) { + this._xhtmlHandler = + new XHTMLHandler(this, (this._result.version == "atom")); + this._reader.contentHandler = this._xhtmlHandler; + return; + } + } - // Check our current state, and see if that state has a defined - // transition. For example, this._trans["atom:entry"]["atom:author"] - // will have one, and it tells us to add an item to our authors array. - if (this._trans[this._state] && this._trans[this._state][key]) { - elementInfo = this._trans[this._state][key]; - } else { - // If we don't have a transition, hand off to extension handler - this._extensionHandler = new ExtensionHandler(this); - this._reader.contentHandler = this._extensionHandler; - this._extensionHandler.startElement(uri, localName, qName, attributes); - return; - } + // Check our current state, and see if that state has a defined + // transition. For example, this._trans["atom:entry"]["atom:author"] + // will have one, and it tells us to add an item to our authors array. + if (this._trans[this._state] && this._trans[this._state][key]) { + elementInfo = this._trans[this._state][key]; + } else { + // If we don't have a transition, hand off to extension handler + this._extensionHandler = new ExtensionHandler(this); + this._reader.contentHandler = this._extensionHandler; + this._extensionHandler.startElement(uri, localName, qName, attributes); + return; + } - // This distinguishes wrappers like 'channel' from elements - // we'd actually like to do something with (which will test true). - this._handlerStack[this._depth] = elementInfo; - if (elementInfo.isWrapper) { - this._state = "IN_" + elementInfo.fieldName.toUpperCase(); - this._stack.push([this._feed, this._state]); - } else if (elementInfo.feedVersion) { - this._state = "IN_" + elementInfo.fieldName.toUpperCase(); + // This distinguishes wrappers like 'channel' from elements + // we'd actually like to do something with (which will test true). + this._handlerStack[this._depth] = elementInfo; + if (elementInfo.isWrapper) { + this._state = "IN_" + elementInfo.fieldName.toUpperCase(); + this._stack.push([this._feed, this._state]); + } else if (elementInfo.feedVersion) { + this._state = "IN_" + elementInfo.fieldName.toUpperCase(); - // Check for the older RSS2 variants - if (elementInfo.feedVersion == "rss2") - elementInfo.feedVersion = this._findRSSVersion(attributes); - else if (uri == RSS090NS) - elementInfo.feedVersion = "rss090"; + // Check for the older RSS2 variants + if (elementInfo.feedVersion == "rss2") + elementInfo.feedVersion = this._findRSSVersion(attributes); + else if (uri == RSS090NS) + elementInfo.feedVersion = "rss090"; - this._docVerified(elementInfo.feedVersion); - this._stack.push([this._feed, this._state]); - this._mapAttributes(this._feed, attributes); - } else { - this._state = this._processComplexElement(elementInfo, attributes); - } - }, + this._docVerified(elementInfo.feedVersion); + this._stack.push([this._feed, this._state]); + this._mapAttributes(this._feed, attributes); + } else { + this._state = this._processComplexElement(elementInfo, attributes); + } + }, - // In the endElement handler, we decrement the stack and look - // for cleanup/transition functions to execute. The second part - // of the state transition works as above in startElement, but - // the state we're looking for is prefixed with an underscore - // to distinguish endElement events from startElement events. - endElement: function FP_endElement(uri, localName, qName) { - var elementInfo = this._handlerStack[this._depth]; - // LOG(""); - if (elementInfo && !elementInfo.isWrapper) - this._closeComplexElement(elementInfo); + // In the endElement handler, we decrement the stack and look + // for cleanup/transition functions to execute. The second part + // of the state transition works as above in startElement, but + // the state we're looking for is prefixed with an underscore + // to distinguish endElement events from startElement events. + endElement: function FP_endElement(uri, localName, qName) { + var elementInfo = this._handlerStack[this._depth]; + // LOG(""); + if (elementInfo && !elementInfo.isWrapper) + this._closeComplexElement(elementInfo); - // cut down xml:base context - if (this._xmlBaseStack.length == this._depth + 1) - this._xmlBaseStack = this._xmlBaseStack.slice(0, this._depth); + // cut down xml:base context + if (this._xmlBaseStack.length == this._depth + 1) + this._xmlBaseStack = this._xmlBaseStack.slice(0, this._depth); - // our new state is whatever is at the top of the stack now - if (this._stack.length > 0) - this._state = this._stack[this._stack.length - 1][1]; - this._handlerStack = this._handlerStack.slice(0, this._depth); - --this._depth; - }, + // our new state is whatever is at the top of the stack now + if (this._stack.length > 0) + this._state = this._stack[this._stack.length - 1][1]; + this._handlerStack = this._handlerStack.slice(0, this._depth); + --this._depth; + }, - // Buffer up character data. The buffer is cleared with every - // opening element. - characters: function FP_characters(data) { - this._buf += data; - }, + // Buffer up character data. The buffer is cleared with every + // opening element. + characters: function FP_characters(data) { + this._buf += data; + }, - processingInstruction: function FP_processingInstruction(target, data) { - if (target == "xml-stylesheet") { - var hrefAttribute = data.match(/href=[\"\'](.*?)[\"\']/); - if (hrefAttribute && hrefAttribute.length == 2) - this._result.stylesheet = strToURI(hrefAttribute[1], this._result.uri); - } - }, + processingInstruction: function FP_processingInstruction(target, data) { + if (target == "xml-stylesheet") { + var hrefAttribute = data.match(/href=[\"\'](.*?)[\"\']/); + if (hrefAttribute && hrefAttribute.length == 2) + this._result.stylesheet = strToURI(hrefAttribute[1], this._result.uri); + } + }, - // end of nsISAXContentHandler + // end of nsISAXContentHandler - // Handle our more complicated elements--those that contain - // attributes and child elements. - _processComplexElement: - function FP__processComplexElement(elementInfo, attributes) { - var obj; + // Handle our more complicated elements--those that contain + // attributes and child elements. + _processComplexElement: + function FP__processComplexElement(elementInfo, attributes) { + var obj; - // If the container is an entry/item, it'll need to have its - // more esoteric properties put in the 'fields' property bag. - if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) { - obj = elementInfo.containerClass.createInstance(Ci.nsIFeedEntry); - obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1]; - this._mapAttributes(obj.fields, attributes); - } else if (elementInfo.containerClass) { - obj = elementInfo.containerClass.createInstance(Ci.nsIFeedElementBase); - obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1]; - obj.attributes = attributes; // just set the SAX attributes - } else { - obj = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); - this._mapAttributes(obj, attributes); - } + // If the container is an entry/item, it'll need to have its + // more esoteric properties put in the 'fields' property bag. + if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) { + obj = elementInfo.containerClass.createInstance(Ci.nsIFeedEntry); + obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1]; + this._mapAttributes(obj.fields, attributes); + } else if (elementInfo.containerClass) { + obj = elementInfo.containerClass.createInstance(Ci.nsIFeedElementBase); + obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1]; + obj.attributes = attributes; // just set the SAX attributes + } else { + obj = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2); + this._mapAttributes(obj, attributes); + } - // We should have a container/propertyBag that's had its - // attributes processed. Now we need to attach it to its - // container. - var newProp; + // We should have a container/propertyBag that's had its + // attributes processed. Now we need to attach it to its + // container. + var newProp; - // First we'll see what's on top of the stack. - var container = this._stack[this._stack.length - 1][0]; + // First we'll see what's on top of the stack. + var container = this._stack[this._stack.length - 1][0]; - // Check to see if it has the property - var prop; - try { - prop = container.getProperty(elementInfo.fieldName); - } catch (e) { - } + // Check to see if it has the property + var prop; + try { + prop = container.getProperty(elementInfo.fieldName); + } catch (e) { + } - if (elementInfo.isArray) { - if (!prop) { - container.setPropertyAsInterface(elementInfo.fieldName, - Cc[ARRAY_CONTRACTID]. - createInstance(Ci.nsIMutableArray)); - } + if (elementInfo.isArray) { + if (!prop) { + container.setPropertyAsInterface(elementInfo.fieldName, + Cc[ARRAY_CONTRACTID]. + createInstance(Ci.nsIMutableArray)); + } - newProp = container.getProperty(elementInfo.fieldName); - // XXX This QI should not be necessary, but XPConnect seems to fly - // off the handle in the browser, and loses track of the interface - // on large files. Bug 335638. - newProp.QueryInterface(Ci.nsIMutableArray); - newProp.appendElement(obj); + newProp = container.getProperty(elementInfo.fieldName); + // XXX This QI should not be necessary, but XPConnect seems to fly + // 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 - // its member nsIPropertyBag instead. - if (isIFeedContainer(obj)) - newProp = obj.fields; + // If new object is an nsIFeedContainer, we want to deal with + // its member nsIPropertyBag instead. + if (isIFeedContainer(obj)) + newProp = obj.fields; - } else { - // If it doesn't, set it. - if (!prop) { - container.setPropertyAsInterface(elementInfo.fieldName, obj); - } - newProp = container.getProperty(elementInfo.fieldName); - } + } else { + // If it doesn't, set it. + if (!prop) { + container.setPropertyAsInterface(elementInfo.fieldName, obj); + } + newProp = container.getProperty(elementInfo.fieldName); + } - // make our new state name, and push the property onto the stack - var newState = "IN_" + elementInfo.fieldName.toUpperCase(); - this._stack.push([newProp, newState, obj]); - return newState; - }, + // make our new state name, and push the property onto the stack + var newState = "IN_" + elementInfo.fieldName.toUpperCase(); + this._stack.push([newProp, newState, obj]); + return newState; + }, - // Sometimes we need reconcile the element content with the object - // model for a given feed. We use helper functions to do the - // munging, but we need to identify array types here, so the munging - // happens only to the last element of an array. - _closeComplexElement: function FP__closeComplexElement(elementInfo) { - var stateTuple = this._stack.pop(); - var container = stateTuple[0]; - var containerParent = stateTuple[2]; - var element = null; - var isArray = isIArray(container); + // Sometimes we need reconcile the element content with the object + // model for a given feed. We use helper functions to do the + // munging, but we need to identify array types here, so the munging + // happens only to the last element of an array. + _closeComplexElement: function FP__closeComplexElement(elementInfo) { + var stateTuple = this._stack.pop(); + var container = stateTuple[0]; + var containerParent = stateTuple[2]; + var element = null; + var isArray = isIArray(container); - // If it's an array and we have to post-process, - // grab the last element - if (isArray) - element = container.queryElementAt(container.length - 1, Ci.nsISupports); - else - element = container; + // If it's an array and we have to post-process, + // grab the last element + if (isArray) + element = container.queryElementAt(container.length - 1, Ci.nsISupports); + else + element = container; - // Run the post-processing function if there is one. - if (elementInfo.closeFunc) - element = elementInfo.closeFunc(this._buf, element); + // Run the post-processing function if there is one. + if (elementInfo.closeFunc) + element = elementInfo.closeFunc(this._buf, element); - // If an nsIFeedContainer was on top of the stack, - // we need to normalize it - if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) - containerParent.normalize(); + // If an nsIFeedContainer was on top of the stack, + // we need to normalize it + if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) + containerParent.normalize(); - // If it's an array, re-set the last element - if (isArray) - container.replaceElementAt(element, container.length - 1); - }, + // If it's an array, re-set the last element + if (isArray) + container.replaceElementAt(element, container.length - 1); + }, - _prefixForNS: function FP_prefixForNS(uri) { - if (!uri) - return ""; - var prefix = gNamespaces[uri]; - if (prefix) - return prefix + ":"; - if (uri.toLowerCase().indexOf("http://backend.userland.com") == 0) - return ""; - return null; - }, + _prefixForNS: function FP_prefixForNS(uri) { + if (!uri) + return ""; + var prefix = gNamespaces[uri]; + if (prefix) + return prefix + ":"; + if (uri.toLowerCase().indexOf("http://backend.userland.com") == 0) + return ""; + return null; + }, - _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) { - var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i); - var val = attributes.getValue(i); - bag.setPropertyAsAString(key, val); - } - }, + _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) { + var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i); + var val = attributes.getValue(i); + bag.setPropertyAsAString(key, val); + } + }, - // Only for RSS2esque formats - _findRSSVersion: function FP__findRSSVersion(attributes) { - var versionAttr = attributes.getValueFromName("", "version").trim(); - var versions = { "0.91": "rss091", - "0.92": "rss092", - "0.93": "rss093", - "0.94": "rss094" }; - if (versions[versionAttr]) - return versions[versionAttr]; - if (versionAttr.substr(0, 2) != "2.") - return "rssUnknown"; - return "rss2"; - }, + // Only for RSS2esque formats + _findRSSVersion: function FP__findRSSVersion(attributes) { + var versionAttr = attributes.getValueFromName("", "version").trim(); + var versions = { "0.91": "rss091", + "0.92": "rss092", + "0.93": "rss093", + "0.94": "rss094" }; + if (versions[versionAttr]) + return versions[versionAttr]; + if (versionAttr.substr(0, 2) != "2.") + return "rssUnknown"; + return "rss2"; + }, - // unknown element values are returned here. See startElement above - // for how this works. - returnFromExtHandler: - function FP_returnExt(uri, localName, chars, attributes) { - --this._depth; + // unknown element values are returned here. See startElement above + // for how this works. + returnFromExtHandler: + function FP_returnExt(uri, localName, chars, attributes) { + --this._depth; - // take control of the SAX events - this._reader.contentHandler = this; - if (localName == null && chars == null) - return; + // take control of the SAX events + this._reader.contentHandler = this; + if (localName == null && chars == null) + return; - // we don't take random elements inside rdf:RDF - if (this._state == "IN_RDF") - return; + // we don't take random elements inside rdf:RDF + if (this._state == "IN_RDF") + return; - // Grab the top of the stack - var top = this._stack[this._stack.length - 1]; - if (!top) - return; + // Grab the top of the stack + var top = this._stack[this._stack.length - 1]; + if (!top) + return; - var container = top[0]; - // Grab the last element if it's an array - if (isIArray(container)) { - var contract = this._handlerStack[this._depth].containerClass; - // check if it's something specific, but not an entry - if (contract && contract != Cc[ENTRY_CONTRACTID]) { - var el = container.queryElementAt(container.length - 1, - Ci.nsIFeedElementBase); - // XXX there must be a way to flatten these interfaces - if (contract == Cc[PERSON_CONTRACTID]) - el.QueryInterface(Ci.nsIFeedPerson); - else - return; // don't know about this interface + var container = top[0]; + // Grab the last element if it's an array + if (isIArray(container)) { + var contract = this._handlerStack[this._depth].containerClass; + // check if it's something specific, but not an entry + if (contract && contract != Cc[ENTRY_CONTRACTID]) { + var el = container.queryElementAt(container.length - 1, + Ci.nsIFeedElementBase); + // XXX there must be a way to flatten these interfaces + if (contract == Cc[PERSON_CONTRACTID]) + el.QueryInterface(Ci.nsIFeedPerson); + else + return; // don't know about this interface - let propName = localName; - var prefix = gNamespaces[uri]; + let propName = localName; + var prefix = gNamespaces[uri]; - // synonyms - if ((uri == "" || - prefix && - ((prefix.indexOf("atom") > -1) || - (prefix.indexOf("rss") > -1))) && - (propName == "url" || propName == "href")) - propName = "uri"; + // synonyms + if ((uri == "" || + prefix && + ((prefix.indexOf("atom") > -1) || + (prefix.indexOf("rss") > -1))) && + (propName == "url" || propName == "href")) + propName = "uri"; - try { - if (el[propName] !== "undefined") { - var propValue = chars; - // convert URI-bearing values to an nsIURI - if (propName == "uri") { - var base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; - propValue = strToURI(chars, base); - } - el[propName] = propValue; - } - } catch (e) { - // ignore XPConnect errors - } - // the rest of the function deals with entry- and feed-level stuff - return; - } - container = container.queryElementAt(container.length - 1, - Ci.nsIWritablePropertyBag2); - } + try { + if (el[propName] !== "undefined") { + var propValue = chars; + // convert URI-bearing values to an nsIURI + if (propName == "uri") { + var base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; + propValue = strToURI(chars, base); + } + el[propName] = propValue; + } + } catch (e) { + // ignore XPConnect errors + } + // the rest of the function deals with entry- and feed-level stuff + return; + } + container = container.queryElementAt(container.length - 1, + Ci.nsIWritablePropertyBag2); + } - // Make the buffer our new property - var propName = this._prefixForNS(uri) + localName; + // Make the buffer our new property + var propName = this._prefixForNS(uri) + localName; - // But, it could be something containing HTML. If so, - // we need to know about that. - if (this._textConstructs[propName] != null && - this._handlerStack[this._depth].containerClass !== null) { - var newProp = Cc[TEXTCONSTRUCT_CONTRACTID]. - createInstance(Ci.nsIFeedTextConstruct); - newProp.text = chars; - // Look up the default type in our table - var type = this._textConstructs[propName]; - var typeAttribute = attributes.getValueFromName("", "type"); - if (this._result.version == "atom" && typeAttribute != null) { - type = typeAttribute; - } else if (this._result.version == "atom03" && typeAttribute != null) { - if (typeAttribute.toLowerCase().includes("xhtml")) { - type = "xhtml"; - } else if (typeAttribute.toLowerCase().includes("html")) { - type = "html"; - } else if (typeAttribute.toLowerCase().includes("text")) { - type = "text"; - } - } + // But, it could be something containing HTML. If so, + // we need to know about that. + if (this._textConstructs[propName] != null && + this._handlerStack[this._depth].containerClass !== null) { + var newProp = Cc[TEXTCONSTRUCT_CONTRACTID]. + createInstance(Ci.nsIFeedTextConstruct); + newProp.text = chars; + // Look up the default type in our table + var type = this._textConstructs[propName]; + var typeAttribute = attributes.getValueFromName("", "type"); + if (this._result.version == "atom" && typeAttribute != null) { + type = typeAttribute; + } else if (this._result.version == "atom03" && typeAttribute != null) { + if (typeAttribute.toLowerCase().includes("xhtml")) { + type = "xhtml"; + } else if (typeAttribute.toLowerCase().includes("html")) { + type = "html"; + } else if (typeAttribute.toLowerCase().includes("text")) { + type = "text"; + } + } - // If it's rss feed-level description, it's not supposed to have html - if (this._result.version.includes("rss") && - this._handlerStack[this._depth].containerClass != ENTRY_CONTRACTID) { - type = "text"; - } - newProp.type = type; - newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; - container.setPropertyAsInterface(propName, newProp); - } else { - container.setPropertyAsAString(propName, chars); - } - }, + // If it's rss feed-level description, it's not supposed to have html + if (this._result.version.includes("rss") && + this._handlerStack[this._depth].containerClass != ENTRY_CONTRACTID) { + type = "text"; + } + newProp.type = type; + newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; + container.setPropertyAsInterface(propName, newProp); + } else { + container.setPropertyAsAString(propName, chars); + } + }, - // Sometimes, we'll hand off SAX handling duties to an XHTMLHandler - // (see above) that will scrape out non-XHTML stuff, normalize - // namespaces, and remove the wrapper div from Atom 1.0. When the - // XHTMLHandler is done, it'll callback here. - returnFromXHTMLHandler: - function FP_returnFromXHTMLHandler(chars, uri, localName, qName) { - // retake control of the SAX content events - this._reader.contentHandler = this; + // Sometimes, we'll hand off SAX handling duties to an XHTMLHandler + // (see above) that will scrape out non-XHTML stuff, normalize + // namespaces, and remove the wrapper div from Atom 1.0. When the + // XHTMLHandler is done, it'll callback here. + returnFromXHTMLHandler: + function FP_returnFromXHTMLHandler(chars, uri, localName, qName) { + // retake control of the SAX content events + this._reader.contentHandler = this; - // Grab the top of the stack - var top = this._stack[this._stack.length - 1]; - if (!top) - return; - var container = top[0]; + // Grab the top of the stack + var top = this._stack[this._stack.length - 1]; + if (!top) + return; + var container = top[0]; - // Assign the property - var newProp = newProp = Cc[TEXTCONSTRUCT_CONTRACTID]. - createInstance(Ci.nsIFeedTextConstruct); - newProp.text = chars; - newProp.type = "xhtml"; - newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; - container.setPropertyAsInterface(this._prefixForNS(uri) + localName, - newProp); + // Assign the property + var newProp = newProp = Cc[TEXTCONSTRUCT_CONTRACTID]. + createInstance(Ci.nsIFeedTextConstruct); + newProp.text = chars; + newProp.type = "xhtml"; + newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1]; + container.setPropertyAsInterface(this._prefixForNS(uri) + localName, + newProp); - // XHTML will cause us to peek too far. The XHTML handler will - // send us an end element to call. RFC4287-valid feeds allow a - // more graceful way to handle this. Unfortunately, we can't count - // on compliance at this point. - this.endElement(uri, localName, qName); - }, + // XHTML will cause us to peek too far. The XHTML handler will + // send us an end element to call. RFC4287-valid feeds allow a + // more graceful way to handle this. Unfortunately, we can't count + // on compliance at this point. + this.endElement(uri, localName, qName); + }, - // XPCOM stuff - classID: FP_CLASSID, - QueryInterface: ChromeUtils.generateQI( - [Ci.nsIFeedProcessor, Ci.nsISAXContentHandler, Ci.nsISAXErrorHandler, - Ci.nsIStreamListener, Ci.nsIRequestObserver] - ), + // XPCOM stuff + classID: FP_CLASSID, + QueryInterface: ChromeUtils.generateQI( + [Ci.nsIFeedProcessor, Ci.nsISAXContentHandler, Ci.nsISAXErrorHandler, + Ci.nsIStreamListener, Ci.nsIRequestObserver] + ), }; var components = [FeedProcessor, FeedResult, Feed, Entry, - TextConstruct, Generator, Person]; + TextConstruct, Generator, Person]; this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components); diff --git a/resource/feeds/nsIFeed.idl b/resource/feeds/nsIFeed.idl index ad87ad9d3e..c1156016a9 100644 --- a/resource/feeds/nsIFeed.idl +++ b/resource/feeds/nsIFeed.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -14,73 +13,73 @@ interface nsIFeedGenerator; [scriptable, uuid(3b8aae33-80e2-4efa-99c8-a6c5b99f76ea)] interface nsIFeed : nsIFeedContainer { - /** - * Uses description, subtitle, and extensions - * to generate a summary. - */ - attribute nsIFeedTextConstruct subtitle; + /** + * Uses description, subtitle, and extensions + * to generate a summary. + */ + attribute nsIFeedTextConstruct subtitle; - // All content classifies as a "feed" - it is the transport. - const unsigned long TYPE_FEED = 0; - const unsigned long TYPE_AUDIO = 1; - const unsigned long TYPE_IMAGE = 2; - const unsigned long TYPE_VIDEO = 4; + // All content classifies as a "feed" - it is the transport. + const unsigned long TYPE_FEED = 0; + const unsigned long TYPE_AUDIO = 1; + const unsigned long TYPE_IMAGE = 2; + const unsigned long TYPE_VIDEO = 4; - /** - * The type of feed. For example, a podcast would be TYPE_AUDIO. - */ - readonly attribute unsigned long type; - - /** - * The total number of enclosures found in the feed. - */ - attribute long enclosureCount; + /** + * The type of feed. For example, a podcast would be TYPE_AUDIO. + */ + readonly attribute unsigned long type; + + /** + * The total number of enclosures found in the feed. + */ + attribute long enclosureCount; - /** - * The items or entries in feed. - */ - attribute nsIArray items; + /** + * The items or entries in feed. + */ + attribute nsIArray items; - /** - * No one really knows what cloud is for. - * - * It supposedly enables some sort of interaction with an XML-RPC or - * SOAP service. - */ - attribute nsIWritablePropertyBag2 cloud; + /** + * No one really knows what cloud is for. + * + * It supposedly enables some sort of interaction with an XML-RPC or + * SOAP service. + */ + attribute nsIWritablePropertyBag2 cloud; - /** - * Information about the software that produced the feed. - */ - attribute nsIFeedGenerator generator; + /** + * Information about the software that produced the feed. + */ + attribute nsIFeedGenerator generator; - /** - * An image url and some metadata (as defined by RSS2). - * - */ - attribute nsIWritablePropertyBag2 image; + /** + * An image url and some metadata (as defined by RSS2). + * + */ + attribute nsIWritablePropertyBag2 image; - /** - * No one really knows what textInput is for. - * - * See - * - * for more details. - */ - attribute nsIWritablePropertyBag2 textInput; + /** + * No one really knows what textInput is for. + * + * See + * + * for more details. + */ + attribute nsIWritablePropertyBag2 textInput; - /** - * Days to skip fetching. This field was supposed to designate - * intervals for feed fetching. It's not generally implemented. For - * example, if this array contained "Monday", aggregators should not - * fetch the feed on Mondays. - */ - attribute nsIArray skipDays; + /** + * Days to skip fetching. This field was supposed to designate + * intervals for feed fetching. It's not generally implemented. For + * example, if this array contained "Monday", aggregators should not + * fetch the feed on Mondays. + */ + attribute nsIArray skipDays; /** - * Hours to skip fetching. This field was supposed to designate - * intervals for feed fetching. It's not generally implemented. See - * for more information. - */ - attribute nsIArray skipHours; + * Hours to skip fetching. This field was supposed to designate + * intervals for feed fetching. It's not generally implemented. See + * for more information. + */ + attribute nsIArray skipHours; }; diff --git a/resource/feeds/nsIFeedContainer.idl b/resource/feeds/nsIFeedContainer.idl index 58de494a51..d288035eef 100644 --- a/resource/feeds/nsIFeedContainer.idl +++ b/resource/feeds/nsIFeedContainer.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -18,68 +17,68 @@ interface nsIFeedTextConstruct; [scriptable, uuid(577a1b4c-b3d4-4c76-9cf8-753e6606114f)] interface nsIFeedContainer : nsIFeedElementBase { - /** - * Many feeds contain an ID distinct from their URI, and - * entries have standard fields for this in all major formats. - */ - attribute AString id; + /** + * Many feeds contain an ID distinct from their URI, and + * entries have standard fields for this in all major formats. + */ + attribute AString id; - /** - * The fields found in the document. Common Atom - * and RSS fields are normalized. This includes some namespaced - * extensions such as dc:subject and content:encoded. - * Consumers can avoid normalization by checking the feed type - * and accessing specific fields. - * - * Common namespaces are accessed using prefixes, like get("dc:subject");. - * See nsIFeedResult::registerExtensionPrefix. - */ - attribute nsIWritablePropertyBag2 fields; + /** + * The fields found in the document. Common Atom + * and RSS fields are normalized. This includes some namespaced + * extensions such as dc:subject and content:encoded. + * Consumers can avoid normalization by checking the feed type + * and accessing specific fields. + * + * Common namespaces are accessed using prefixes, like get("dc:subject");. + * See nsIFeedResult::registerExtensionPrefix. + */ + attribute nsIWritablePropertyBag2 fields; - /** - * Sometimes there's no title, or the title contains markup, so take - * care in decoding the attribute. - */ - attribute nsIFeedTextConstruct title; + /** + * Sometimes there's no title, or the title contains markup, so take + * care in decoding the attribute. + */ + attribute nsIFeedTextConstruct title; - /** - * Returns the primary link for the feed or entry. - */ - attribute nsIURI link; + /** + * Returns the primary link for the feed or entry. + */ + attribute nsIURI link; - /** - * Returns all links for a feed or entry. - */ - attribute nsIArray links; + /** + * Returns all links for a feed or entry. + */ + attribute nsIArray links; - /** - * Returns the categories found in a feed or entry. - */ - attribute nsIArray categories; + /** + * Returns the categories found in a feed or entry. + */ + attribute nsIArray categories; - /** - * The rights or license associated with a feed or entry. - */ - attribute nsIFeedTextConstruct rights; + /** + * The rights or license associated with a feed or entry. + */ + attribute nsIFeedTextConstruct rights; - /** - * A list of nsIFeedPersons that authored the feed. - */ - attribute nsIArray authors; + /** + * A list of nsIFeedPersons that authored the feed. + */ + attribute nsIArray authors; - /** - * A list of nsIFeedPersons that contributed to the feed. - */ - attribute nsIArray contributors; + /** + * A list of nsIFeedPersons that contributed to the feed. + */ + attribute nsIArray contributors; - /** - * The date the feed was updated, in RFC822 form. Parsable by JS - * and mail code. - */ - attribute AString updated; + /** + * The date the feed was updated, in RFC822 form. Parsable by JS + * and mail code. + */ + attribute AString updated; - /** - * Syncs a container's fields with its convenience attributes. - */ - void normalize(); + /** + * Syncs a container's fields with its convenience attributes. + */ + void normalize(); }; diff --git a/resource/feeds/nsIFeedElementBase.idl b/resource/feeds/nsIFeedElementBase.idl index 1b8975ae5a..a8364160ca 100644 --- a/resource/feeds/nsIFeedElementBase.idl +++ b/resource/feeds/nsIFeedElementBase.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -14,15 +13,15 @@ interface nsIURI; [scriptable, uuid(5215291e-fa0a-40c2-8ce7-e86cd1a1d3fa)] interface nsIFeedElementBase : nsISupports { - /** - * The attributes found on the element. Most interfaces provide convenience - * accessors for their standard fields, so this useful only when looking for - * an extension. - */ - attribute nsISAXAttributes attributes; + /** + * The attributes found on the element. Most interfaces provide convenience + * accessors for their standard fields, so this useful only when looking for + * an extension. + */ + attribute nsISAXAttributes attributes; - /** - * The baseURI for the Entry or Feed. - */ - attribute nsIURI baseURI; + /** + * The baseURI for the Entry or Feed. + */ + attribute nsIURI baseURI; }; diff --git a/resource/feeds/nsIFeedEntry.idl b/resource/feeds/nsIFeedEntry.idl index 83646aadb6..88778e9966 100644 --- a/resource/feeds/nsIFeedEntry.idl +++ b/resource/feeds/nsIFeedEntry.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -14,33 +13,33 @@ interface nsIArray; [scriptable, uuid(31bfd5b4-8ff5-4bfd-a8cb-b3dfbd4f0a5b)] interface nsIFeedEntry : nsIFeedContainer { - /** - * Uses description, subtitle, summary, content and extensions - * to generate a summary. - * - */ - attribute nsIFeedTextConstruct summary; + /** + * Uses description, subtitle, summary, content and extensions + * to generate a summary. + * + */ + attribute nsIFeedTextConstruct summary; - /** - * The date the entry was published, in RFC822 form. Parsable by JS - * and mail code. - */ - attribute AString published; + /** + * The date the entry was published, in RFC822 form. Parsable by JS + * and mail code. + */ + attribute AString published; - /** - * Uses atom:content and content:encoded to provide - * a 'full text' view of an entry. - * - */ - attribute nsIFeedTextConstruct content; + /** + * Uses atom:content and content:encoded to provide + * a 'full text' view of an entry. + * + */ + attribute nsIFeedTextConstruct content; - /** - * Enclosures are podcasts, photocasts, etc. - */ - attribute nsIArray enclosures; + /** + * Enclosures are podcasts, photocasts, etc. + */ + attribute nsIArray enclosures; - /** - * Enclosures, etc. that might be displayed inline. - */ - attribute nsIArray mediaContent; + /** + * Enclosures, etc. that might be displayed inline. + */ + attribute nsIArray mediaContent; }; diff --git a/resource/feeds/nsIFeedGenerator.idl b/resource/feeds/nsIFeedGenerator.idl index 3c23ca1424..4ec956543f 100644 --- a/resource/feeds/nsIFeedGenerator.idl +++ b/resource/feeds/nsIFeedGenerator.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -13,18 +12,18 @@ interface nsIURI; [scriptable, uuid(0fecd56b-bd92-481b-a486-b8d489cdd385)] interface nsIFeedGenerator : nsIFeedElementBase { - /** - * The name of the software. - */ - attribute AString agent; + /** + * The name of the software. + */ + attribute AString agent; - /** - * The version of the software. - */ - attribute AString version; + /** + * The version of the software. + */ + attribute AString version; - /** - * A URI associated with the software. - */ - attribute nsIURI uri; + /** + * A URI associated with the software. + */ + attribute nsIURI uri; }; diff --git a/resource/feeds/nsIFeedListener.idl b/resource/feeds/nsIFeedListener.idl index 6826d04a41..8bca4b716a 100644 --- a/resource/feeds/nsIFeedListener.idl +++ b/resource/feeds/nsIFeedListener.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -14,16 +13,16 @@ interface nsIFeedEntry; [scriptable, uuid(4d2ebe88-36eb-4e20-bcd1-997b3c1f24ce)] interface nsIFeedResultListener : nsISupports { - /** - * Always called, even after an error. There could be new feed-level - * data available at this point, if it followed or was interspersed - * with the items. Fire-and-Forget implementations only need this. - * - * @param result - * An object implementing nsIFeedResult representing the feed - * and its metadata. - */ - void handleResult(in nsIFeedResult result); + /** + * Always called, even after an error. There could be new feed-level + * data available at this point, if it followed or was interspersed + * with the items. Fire-and-Forget implementations only need this. + * + * @param result + * An object implementing nsIFeedResult representing the feed + * and its metadata. + */ + void handleResult(in nsIFeedResult result); }; @@ -34,54 +33,54 @@ interface nsIFeedResultListener : nsISupports [scriptable, uuid(ebfd5de5-713c-40c0-ad7c-f095117fa580)] interface nsIFeedProgressListener : nsIFeedResultListener { - /** - * ReportError will be called in the event of fatal - * XML errors, or if the document is not a feed. The bozo - * bit will be set if the error was due to a fatal error. - * - * @param errorText - * A short description of the error. - * @param lineNumber - * The line on which the error occurred. - */ - void reportError(in AString errorText, in long lineNumber, - in boolean bozo); - - /** - * StartFeed will be called as soon as a reasonable start to - * a feed is detected. - * - * @param result - * An object implementing nsIFeedResult representing the feed - * and its metadata. At this point, the result has version - * information. - */ - void handleStartFeed(in nsIFeedResult result); + /** + * ReportError will be called in the event of fatal + * XML errors, or if the document is not a feed. The bozo + * bit will be set if the error was due to a fatal error. + * + * @param errorText + * A short description of the error. + * @param lineNumber + * The line on which the error occurred. + */ + void reportError(in AString errorText, in long lineNumber, + in boolean bozo); + + /** + * StartFeed will be called as soon as a reasonable start to + * a feed is detected. + * + * @param result + * An object implementing nsIFeedResult representing the feed + * and its metadata. At this point, the result has version + * information. + */ + void handleStartFeed(in nsIFeedResult result); - /** - * Called when the first entry/item is encountered. In Atom, all - * feed data is required to preceed the entries. In RSS, the data - * usually does. If the type is one of the entry/item-only types, - * this event will not be called. - * - * @param result - * An object implementing nsIFeedResult representing the feed - * and its metadata. At this point, the result will likely have - * most of its feed-level metadata. - */ - void handleFeedAtFirstEntry(in nsIFeedResult result); + /** + * Called when the first entry/item is encountered. In Atom, all + * feed data is required to preceed the entries. In RSS, the data + * usually does. If the type is one of the entry/item-only types, + * this event will not be called. + * + * @param result + * An object implementing nsIFeedResult representing the feed + * and its metadata. At this point, the result will likely have + * most of its feed-level metadata. + */ + void handleFeedAtFirstEntry(in nsIFeedResult result); - /** - * Called after each entry/item. If the document is a standalone - * item or entry, this HandleFeedAtFirstEntry will not have been - * called. Also, this entry's parent field will be null. - * - * @param entry - * An object implementing nsIFeedEntry that represents the latest - * entry encountered. - * @param result - * An object implementing nsIFeedResult representing the feed - * and its metadata. - */ - void handleEntry(in nsIFeedEntry entry, in nsIFeedResult result); + /** + * Called after each entry/item. If the document is a standalone + * item or entry, this HandleFeedAtFirstEntry will not have been + * called. Also, this entry's parent field will be null. + * + * @param entry + * An object implementing nsIFeedEntry that represents the latest + * entry encountered. + * @param result + * An object implementing nsIFeedResult representing the feed + * and its metadata. + */ + void handleEntry(in nsIFeedEntry entry, in nsIFeedResult result); }; diff --git a/resource/feeds/nsIFeedPerson.idl b/resource/feeds/nsIFeedPerson.idl index d9d6eb77bf..77de267f60 100644 --- a/resource/feeds/nsIFeedPerson.idl +++ b/resource/feeds/nsIFeedPerson.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -13,18 +12,18 @@ interface nsIURI; [scriptable, uuid(29cbd45f-f2d3-4b28-b557-3ab7a61ecde4)] interface nsIFeedPerson : nsIFeedElementBase { - /** - * The name of the person. - */ - attribute AString name; + /** + * The name of the person. + */ + attribute AString name; - /** - * An email address associated with the person. - */ - attribute AString email; + /** + * An email address associated with the person. + */ + attribute AString email; - /** - * A URI associated with the person (e.g. a homepage). - */ - attribute nsIURI uri; + /** + * A URI associated with the person (e.g. a homepage). + */ + attribute nsIURI uri; }; diff --git a/resource/feeds/nsIFeedProcessor.idl b/resource/feeds/nsIFeedProcessor.idl index eb695e4e77..483dfe656b 100644 --- a/resource/feeds/nsIFeedProcessor.idl +++ b/resource/feeds/nsIFeedProcessor.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -16,26 +15,26 @@ interface nsIInputStream; [scriptable, uuid(8a0b2908-21b0-45d7-b14d-30df0f92afc7)] interface nsIFeedProcessor : nsIStreamListener { - /** - * The listener that will respond to feed events. - */ - attribute nsIFeedResultListener listener; + /** + * The listener that will respond to feed events. + */ + attribute nsIFeedResultListener listener; - // Level is where to listen for the extension, a constant: FEED, - // ENTRY, BOTH. - // - // XXX todo void registerExtensionHandler(in - // nsIFeedExtensionHandler, in long level); - - /** - * Parse a feed asynchronously. The caller must then call the - * nsIFeedProcessor's nsIStreamListener methods to drive the - * parse. Do not call the other parse methods during an asynchronous - * parse. - * - * @param requestObserver The observer to notify on start/stop. This - * argument can be null. - * @param uri The base URI. - */ - void parseAsync(in nsIRequestObserver requestObserver, in nsIURI uri); + // Level is where to listen for the extension, a constant: FEED, + // ENTRY, BOTH. + // + // XXX todo void registerExtensionHandler(in + // nsIFeedExtensionHandler, in long level); + + /** + * Parse a feed asynchronously. The caller must then call the + * nsIFeedProcessor's nsIStreamListener methods to drive the + * parse. Do not call the other parse methods during an asynchronous + * parse. + * + * @param requestObserver The observer to notify on start/stop. This + * argument can be null. + * @param uri The base URI. + */ + void parseAsync(in nsIRequestObserver requestObserver, in nsIURI uri); }; diff --git a/resource/feeds/nsIFeedResult.idl b/resource/feeds/nsIFeedResult.idl index 4cfb0a13ea..beb8420fe0 100644 --- a/resource/feeds/nsIFeedResult.idl +++ b/resource/feeds/nsIFeedResult.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -14,52 +13,52 @@ interface nsIURI; */ [scriptable, uuid(7a180b78-0f46-4569-8c22-f3d720ea1c57)] interface nsIFeedResult : nsISupports { - - /** - * The Feed parser will set the bozo bit when a feed triggers a fatal - * error during XML parsing. There may be entries and feed metadata - * that were parsed before the error. Thanks to Tim Bray for - * suggesting this terminology. - * - */ - attribute boolean bozo; - - /** - * The parsed feed or entry. - * - * Will be null if a non-feed is processed. - */ - attribute nsIFeedContainer doc; + + /** + * The Feed parser will set the bozo bit when a feed triggers a fatal + * error during XML parsing. There may be entries and feed metadata + * that were parsed before the error. Thanks to Tim Bray for + * suggesting this terminology. + * + */ + attribute boolean bozo; + + /** + * The parsed feed or entry. + * + * Will be null if a non-feed is processed. + */ + attribute nsIFeedContainer doc; - /** - * The address from which the feed was fetched. - */ - attribute nsIURI uri; + /** + * The address from which the feed was fetched. + */ + attribute nsIURI uri; - /** - * Feed Version: - * atom, rss2, rss09, rss091, rss091userland, rss092, rss1, atom03, - * atomEntry, rssItem - * - * Will be null if a non-feed is processed. - */ - attribute AString version; + /** + * Feed Version: + * atom, rss2, rss09, rss091, rss091userland, rss092, rss1, atom03, + * atomEntry, rssItem + * + * Will be null if a non-feed is processed. + */ + attribute AString version; - /** - * An XSLT stylesheet available to transform the source of the - * feed. Some feeds include this information in a processing - * instruction. It's generally intended for clients with specific - * feed capabilities. - */ - attribute nsIURI stylesheet; + /** + * An XSLT stylesheet available to transform the source of the + * feed. Some feeds include this information in a processing + * instruction. It's generally intended for clients with specific + * feed capabilities. + */ + attribute nsIURI stylesheet; - /** - * HTTP response headers that accompanied the feed. - */ - attribute nsIProperties headers; + /** + * HTTP response headers that accompanied the feed. + */ + attribute nsIProperties headers; - /** - * Registers a prefix used to access an extension in the feed/entry - */ - void registerExtensionPrefix(in AString aNamespace, in AString aPrefix); + /** + * Registers a prefix used to access an extension in the feed/entry + */ + void registerExtensionPrefix(in AString aNamespace, in AString aPrefix); }; diff --git a/resource/feeds/nsIFeedTextConstruct.idl b/resource/feeds/nsIFeedTextConstruct.idl index 9c77e9c0ff..893611b05b 100644 --- a/resource/feeds/nsIFeedTextConstruct.idl +++ b/resource/feeds/nsIFeedTextConstruct.idl @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -18,41 +17,41 @@ webidl Element; [scriptable, uuid(fc97a2a9-d649-4494-931e-db81a156c873)] interface nsIFeedTextConstruct : nsISupports { - /** - * If the text construct contains (X)HTML, relative references in - * the content should be resolved against this base URI. - */ - attribute nsIURI base; + /** + * If the text construct contains (X)HTML, relative references in + * the content should be resolved against this base URI. + */ + attribute nsIURI base; - /** - * The language of the text. For example, "en-US" for US English. - */ - attribute AString lang; + /** + * The language of the text. For example, "en-US" for US English. + */ + attribute AString lang; - /** - * One of "text", "html", or "xhtml". If the type is (x)html, a '<' - * character represents markup. To display that character, an escape - * such as < must be used. If the type is "text", the '<' - * character represents the character itself, and such text should - * not be embedded in markup without escaping it first. - */ - attribute AString type; + /** + * One of "text", "html", or "xhtml". If the type is (x)html, a '<' + * character represents markup. To display that character, an escape + * such as < must be used. If the type is "text", the '<' + * character represents the character itself, and such text should + * not be embedded in markup without escaping it first. + */ + attribute AString type; - /** - * The content of the text construct. - */ - attribute AString text; + /** + * The content of the text construct. + */ + attribute AString text; - /** - * Returns the text of the text construct, with all markup stripped - * and all entities decoded. If the type attribute's value is "text", - * this function returns the value of the text attribute unchanged. - */ - AString plainText(); + /** + * Returns the text of the text construct, with all markup stripped + * and all entities decoded. If the type attribute's value is "text", + * this function returns the value of the text attribute unchanged. + */ + AString plainText(); - /** - * Return an nsIDocumentFragment containing the text and markup. - */ - DocumentFragment createDocumentFragment(in Element element); + /** + * Return an nsIDocumentFragment containing the text and markup. + */ + DocumentFragment createDocumentFragment(in Element element); };