fix for 250633, sr=mscott don't redownload rss messages we've already downloaded

This commit is contained in:
bienvenu%nventure.com 2004-07-10 02:00:57 +00:00
Родитель 352b310090
Коммит 973fab624e
6 изменённых файлов: 515 добавлений и 94 удалений

Просмотреть файл

@ -15,17 +15,17 @@ var serializer = new XMLSerializer;
// can access the Feed objects after it finishes downloading the feed files.
var gFzFeedCache = new Object();
function Feed(url, quickMode, title) {
this.url = url;
this.quickMode = quickMode || false;
this.title = title || null;
function Feed(resource) {
this.resource = resource.QueryInterface(Components.interfaces.nsIRDFResource);
this.description = null;
this.author = null;
this.description = null;
this.author = null;
this.request = null;
this.request = null;
return this;
this.items = new Array();
return this;
}
// The name of the message folder corresponding to the feed.
@ -92,6 +92,45 @@ Feed.onDownloadError = function(event) {
throw("error downloading feed " + url);
}
Feed.prototype.url getter = function() {
var ds = getSubscriptionsDS();
var url = ds.GetTarget(this.resource, DC_IDENTIFIER, true);
if (url)
url = url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
else
url = this.resource.Value;
return url;
}
Feed.prototype.title getter = function() {
var ds = getSubscriptionsDS();
var title = ds.GetTarget(this.resource, DC_TITLE, true);
if (title)
title = title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
return title;
}
Feed.prototype.title setter = function(new_title) {
var ds = getSubscriptionsDS();
new_title = rdf.GetLiteral(new_title || "");
var old_title = ds.GetTarget(this.resource, DC_TITLE, true);
if (old_title)
ds.Change(this.resource, DC_TITLE, old_title, new_title);
else
ds.Assert(this.resource, DC_TITLE, new_title, true);
}
Feed.prototype.quickMode getter = function() {
var ds = getSubscriptionsDS();
var quickMode = ds.GetTarget(this.resource, FZ_QUICKMODE, true);
if (quickMode) {
quickMode = quickMode.QueryInterface(Components.interfaces.nsIRDFLiteral);
quickMode = quickMode.Value;
quickMode = eval(quickMode);
}
return quickMode;
}
Feed.prototype.parse = function() {
// Figures out what description language (RSS, Atom) and version this feed
// is using and calls a language/version-specific feed parser.
@ -125,6 +164,9 @@ Feed.prototype.parse = function() {
debug(this.url + " is of unknown format; assuming an RSS 0.9x feed");
this.parseAsRSS2();
}
var ds = getItemsDS();
ds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
ds.Flush();
}
Feed.prototype.parseAsRSS2 = function() {
@ -142,6 +184,8 @@ Feed.prototype.parseAsRSS2 = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var itemNodes = this.request.responseXML.getElementsByTagName("item");
for ( var i=0 ; i<itemNodes.length ; i++ ) {
var itemNode = itemNodes[i];
@ -173,7 +217,10 @@ Feed.prototype.parseAsRSS2 = function() {
|| item.date;
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.parseAsRSS1 = function() {
@ -193,6 +240,8 @@ Feed.prototype.parseAsRSS1 = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var items = ds.GetTarget(channel, RSS_ITEMS, true);
//items = items.QueryInterface(Components.interfaces.nsIRDFContainer);
items = rdfcontainer.MakeSeq(ds, items);
@ -227,7 +276,9 @@ Feed.prototype.parseAsRSS1 = function() {
item.content = getRDFTargetValue(ds, itemResource, RSS_CONTENT_ENCODED);
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.parseAsAtom = function() {
@ -245,6 +296,8 @@ Feed.prototype.parseAsAtom = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var items = this.request.responseXML.getElementsByTagName("entry");
for ( var i=0 ; i<items.length ; i++ ) {
var itemNode = items[i];
@ -317,5 +370,42 @@ Feed.prototype.parseAsAtom = function() {
item.content = content;
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.invalidateItems = function invalidateItems() {
var ds = getItemsDS();
debug("invalidating items for " + this.url);
var items = ds.GetSources(FZ_FEED, this.resource, true);
var item;
while (items.hasMoreElements()) {
item = items.getNext();
item = item.QueryInterface(Components.interfaces.nsIRDFResource);
debug("invalidating " + item.Value);
var valid = ds.GetTarget(item, FZ_VALID, true);
if (valid)
ds.Unassert(item, FZ_VALID, valid, true);
}
}
Feed.prototype.removeInvalidItems = function() {
var ds = getItemsDS();
debug("removing invalid items for " + this.url);
var items = ds.GetSources(FZ_FEED, this.resource, true);
var item;
while (items.hasMoreElements()) {
item = items.getNext();
item = item.QueryInterface(Components.interfaces.nsIRDFResource);
if (ds.HasAssertion(item, FZ_VALID, RDF_LITERAL_TRUE, true))
continue;
debug("removing " + item.Value);
ds.Unassert(item, FZ_FEED, this.resource, true);
if (ds.hasArcOut(item, FZ_FEED))
debug(item.Value + " is from more than one feed; only the reference to this feed removed");
else
removeAssertions(ds, item);
}
}

Просмотреть файл

@ -186,7 +186,8 @@ FeedItem.prototype.isStored = function() {
} catch(e) {
folder = null;
}
if (!folder) {
if (!folder)
{
debug(this.feed.name + " folder doesn't exist; creating");
debug("creating " + this.feed.name + "as child of " + server.rootMsgFolder + "\n");
server.rootMsgFolder.createSubfolder(this.feed.name, getMessageWindow());
@ -198,22 +199,56 @@ FeedItem.prototype.isStored = function() {
return false;
}
try {
folder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
var db = folder.getMsgDatabase(getMessageWindow());
var hdr = db.getMsgHdrForMessageID(this.messageID);
if (hdr) {
debug(this.identity + " stored");
return true;
var ds = getItemsDS();
var itemResource = rdf.GetResource(this.url || ("urn:" + this.id));
var downloaded = ds.GetTarget(itemResource, FZ_STORED, true);
if (!downloaded || downloaded.QueryInterface(Components.interfaces.nsIRDFLiteral).Value == "false")
{
debug(this.identity + " not stored");
return false;
}
else
{
debug(this.identity + " stored");
return true;
}
}
// XXX This should happen in the constructor automatically.
FeedItem.prototype.markValid = function() {
debug("validating " + this.url);
var ds = getItemsDS();
var resource = rdf.GetResource(this.url || ("urn:" + this.id));
if (!ds.HasAssertion(resource, FZ_FEED, rdf.GetResource(this.feed.url), true))
ds.Assert(resource, FZ_FEED, rdf.GetResource(this.feed.url), true);
if (ds.hasArcOut(resource, FZ_VALID)) {
var currentValue = ds.GetTarget(resource, FZ_VALID, true);
ds.Change(resource, FZ_VALID, currentValue, RDF_LITERAL_TRUE);
}
else {
return false;
ds.Assert(resource, FZ_VALID, RDF_LITERAL_TRUE, true);
}
}
FeedItem.prototype.markStored = function() {
var ds = getItemsDS();
var resource = rdf.GetResource(this.url || ("urn:" + this.id));
if (!ds.HasAssertion(resource, FZ_FEED, rdf.GetResource(this.feed.url), true))
ds.Assert(resource, FZ_FEED, rdf.GetResource(this.feed.url), true);
var currentValue;
if (ds.hasArcOut(resource, FZ_STORED)) {
currentValue = ds.GetTarget(resource, FZ_STORED, true);
ds.Change(resource, FZ_STORED, currentValue, RDF_LITERAL_TRUE);
}
else {
ds.Assert(resource, FZ_STORED, RDF_LITERAL_TRUE, true);
}
}
catch(e) {
debug(this.identity + " error checking if stored: " + e);
throw(e);
}
}
FeedItem.prototype.download = function() {
@ -319,6 +354,7 @@ FeedItem.prototype.writeToFolder = function() {
var folder = server.rootMsgFolder.getChildNamed(this.feed.name);
folder = folder.QueryInterface(Components.interfaces.nsIMsgLocalMailFolder);
folder.addMessage(source);
this.markStored();
}
function W3CToIETFDate(dateString) {

Просмотреть файл

@ -34,6 +34,7 @@ var gFzStartupTime = new Date();
// Load and cache the subscriptions data source so it's available when we need it.
getSubscriptionsDS();
getItemsDS();
function onLoad() {
// XXX Code to make the News & Blogs toolbar button show up automatically.
@ -47,6 +48,19 @@ function onLoad() {
// currentset += ",button-newsandblogs";
//toolbar.setAttribute('currentset', currentset);
// Make sure the subscriptions and items data source is loaded, since we'll
// need them for everything we do.
var itemsDS =
getItemsDS()
.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (!itemsDS.loaded) {
if (new Date() - gFzStartupTime < 30 * 1000) {
window.setTimeout(onLoad, 1000);
return;
}
else
throw("couldn't load the items datasource within thirty seconds");
}
// Make sure the subscriptions data source is loaded, since we'll need it
// for everything we do. If it's not loaded, recheck it every second until
// it's been ten seconds since we started up, then give up.
@ -78,35 +92,18 @@ function onLoad() {
window.setTimeout(onLoad, gFzStartupDelay * 1000);
function downloadFeeds() {
// Reload subscriptions every 30 minutes (XXX make this configurable via a pref).
window.setTimeout(downloadFeeds, 30 * 60 * 1000);
var ds = getSubscriptionsDS();
var feeds = getSubscriptionsList().GetElements();
var feed;
while(feeds.hasMoreElements())
downloadFeed(feeds.getNext());
}
function downloadFeed(feed) {
var ds = getSubscriptionsDS();
var feeds = getSubscriptionsList().GetElements();
var feed, url, quickMode, title;
while(feeds.hasMoreElements()) {
feed = feeds.getNext();
feed = feed.QueryInterface(Components.interfaces.nsIRDFResource);
url = ds.GetTarget(feed, DC_IDENTIFIER, true);
if (url)
url = url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
quickMode = ds.GetTarget(feed, FZ_QUICKMODE, true);
if (quickMode) {
quickMode = quickMode.QueryInterface(Components.interfaces.nsIRDFLiteral);
quickMode = quickMode.Value;
quickMode = eval(quickMode);
}
title = ds.GetTarget(feed, DC_TITLE, true);
if (title)
title = title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
feed = new Feed(url, quickMode, title);
feed.download();
}
new Feed(feed).download();
}
function migrateSubscriptions(oldFile) {

Просмотреть файл

@ -39,41 +39,47 @@ function doAdd() {
// if the user hit cancel, exit without doing anything
if (!feedProperties.result)
{
debug("feedProperties.result empty\n");
return;
}
if (!feedProperties.feedLocation)
{
debug("feedProperties.feedLocation empty\n");
return;
}
const DEFAULT_FEED_TITLE = "feed title";
const DEFAULT_FEED_URL = "feed location";
feed = new Feed(feedProperties.feedLocation || DEFAULT_FEED_URL);
feed.download(false, false);
if (!feedProperties.feedName)
feedProperties.feedName = DEFAULT_FEED_TITLE;
var itemResource = rdf.GetResource(feedProperties.feedLocation);
feed = new Feed(itemResource);
feed.download(false, false);
debug("after download, feed name = " + feed.name + "\n");
var server = getIncomingServer();
var folder;
try {
//var folder = server.rootMsgFolder.FindSubFolder(feed.name);
folder = server.rootMsgFolder.getChildNamed(feedProperties.feedName);
var folder = server.rootMsgFolder.getChildNamed(feed.name);
}
catch(e) {
// If we're here, it's probably because the folder doesn't exist yet,
// so create it.
debug("folder for new feed " + feedProperties.feedName + " doesn't exist; creating");
debug("creating " + feedProperties.feedName + "as child of " + server.rootMsgFolder + "\n");
server.rootMsgFolder.createSubfolder(feedProperties.feedName, getMessageWindow());
folder = server.rootMsgFolder.FindSubFolder(feedProperties.feedName);
debug("folder for new feed " + feed.name + " doesn't exist; creating");
debug("creating " + feed.name + "as child of " + server.rootMsgFolder + "\n");
server.rootMsgFolder.createSubfolder(feed.name, getMessageWindow());
folder = server.rootMsgFolder.FindSubFolder(feed.name);
var msgdb = folder.getMsgDatabase(null);
var folderInfo = msgdb.dBFolderInfo;
folderInfo.setCharPtrProperty("feedUrl", feedProperties.feedLocation);
}
// XXX This should be something like "subscribe to feed".
dump ("feed name = " + feedProperties.feedName + "\n");
addFeed(feedProperties.feedLocation, feedProperties.feedName, null, folder);
// XXX Maybe we can combine this with the earlier download?
dump ("feed name = " + feed.name + "\n");
addFeed(feedProperties.feedLocation, feed.name, null, folder);
// now download it for real, now that we have a folder.
feed.download();
}
@ -174,7 +180,7 @@ function doEdit() {
// the title, so despite the cancellation we should still redownload
// the feed if the title has changed.
if (new_title != old_title) {
feed = new Feed(old_url, null, feedProperties.feedName);
feed = new Feed(item.id);
feed.download();
}
return;
@ -182,7 +188,7 @@ function doEdit() {
else if (feedProperties.feedLocation != old_url)
updateURL(item.id, feedProperties.feedLocation);
feed = new Feed(feedProperties.feedLocation, null, feedProperties.feedName);
feed = new Feed(item.id);
feed.download();
}
@ -204,8 +210,7 @@ function doRemove() {
var server = getIncomingServer();
var openerResource = server.rootMsgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
var titleValue = title ? title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
var url = ds.GetTarget(resource, DC_IDENTIFIER, true);
var feed = new Feed(url, null, titleValue);
var feed = new Feed(resource);
try {
var folderResource = server.rootMsgFolder.getChildNamed(feed.name).QueryInterface(Components.interfaces.nsIRDFResource);
var foo = window.opener.messenger.DeleteFolders(window.opener.GetFolderDatasource(), openerResource, folderResource);
@ -218,7 +223,7 @@ function doRemove() {
// so don't remove it.
folder = server.rootMsgFolder.getChildNamed(feed.name);
if (folder)
return;
return;
}
catch (e) {}
ds.Unassert(resource, DC_TITLE, title, true);
@ -232,6 +237,23 @@ function doRemove() {
feeds.RemoveElementAt(index, true);
}
// Remove all assertions about the feed from the subscriptions database.
var ds = getSubscriptionsDS();
removeAssertions(ds, feed);
// Remove all assertions about items in the feed from the items database.
ds = getItemsDS();
var items = ds.GetSources(FZ_FEED, feed, true);
while (items.hasMoreElements()) {
var item = items.getNext();
item = item.QueryInterface(Components.interfaces.nsIRDFResource);
ds.Unassert(item, FZ_FEED, feed, true);
if (ds.hasArcOut(item, FZ_FEED))
debug(item.Value + " is from more than one feed; only the reference to this feed removed");
else
removeAssertions(ds, item);
}
//tree.builder.rebuild();
}

Просмотреть файл

@ -40,6 +40,11 @@ const FZ_FEEDS = rdf.GetResource(FZ_NS + "feeds");
const FZ_FEED = rdf.GetResource(FZ_NS + "feed");
const FZ_QUICKMODE = rdf.GetResource(FZ_NS + "quickMode");
const FZ_DESTFOLDER = rdf.GetResource(FZ_NS + "destFolder");
const FZ_STORED = rdf.GetResource(FZ_NS + "stored");
const FZ_VALID = rdf.GetResource(FZ_NS + "valid");
const RDF_LITERAL_TRUE = rdf.GetLiteral("true");
const RDF_LITERAL_FALSE = rdf.GetLiteral("false");
// XXX There's a containerutils in forumzilla.js that this should be merged with.
var containerUtils =
@ -81,6 +86,11 @@ function addFeed(url, title, quickMode, destFolder) {
ds.Assert(id, FZ_DESTFOLDER, destFolder, true);
ds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
ds.Flush();
// Create a new feed object for the feed.
feed = new Feed(id);
// Downloading the feed synchronously will pick up the title.
feed.download(false, false);
}
@ -184,3 +194,71 @@ function createSubscriptionsFile(file) {
');
file.close();
}
var gFzItemsDS; // cache
function getItemsDS() {
if (gFzItemsDS)
return gFzItemsDS;
var file = getItemsFile();
var url = fileHandler.getURLSpecFromFile(file);
gFzItemsDS = rdf.GetDataSource(url);
if (!gFzItemsDS)
throw("can't get subscriptions data source");
// Note that it this point the datasource may not be loaded yet.
// You have to QueryInterface it to nsIRDFRemoteDataSource and check
// its "loaded" property to be sure. You can also attach an observer
// which will get notified when the load is complete.
return gFzItemsDS;
}
function getItemsFile() {
// Get the app directory service so we can look up the user's profile dir.
var appDirectoryService =
Components
.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
if ( !appDirectoryService )
throw("couldn't get the directory service");
// Get the user's profile directory.
var profileDir =
appDirectoryService.get("ProfD", Components.interfaces.nsIFile);
if ( !profileDir )
throw ("couldn't get the user's profile directory");
// Get the user's subscriptions file.
var file = profileDir.clone();
file.append("feeditems.rdf");
// If the file doesn't exist, create it.
if (!file.exists()) {
var newfile = new LocalFile(file, MODE_WRONLY | MODE_CREATE);
newfile.write('\
<?xml version="1.0"?>\n\
<RDF:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"\n\
xmlns:fz="' + FZ_NS + '"\n\
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n\
</RDF:RDF>\n\
');
newfile.close();
}
return file;
}
function removeAssertions(ds, resource) {
var properties = ds.ArcLabelsOut(resource);
var property;
while (properties.hasMoreElements()) {
property = properties.getNext();
var values = ds.GetTargets(resource, property, true);
var value;
while (values.hasMoreElements()) {
value = values.getNext();
ds.Unassert(resource, property, value, true);
}
}
}

Просмотреть файл

@ -41,10 +41,13 @@ var nsNewsBlogFeedDownloader =
downloadFeed: function(aUrl, aFolder, aQuickMode, aTitle, aUrlListener, aMsgWindow)
{
// we might just pull all these args out of the aFolder DB, instead of passing them in...
feed = new Feed(aUrl, aQuickMode, aTitle);
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
id = rdf.GetResource(aUrl);
feed = new Feed(id);
feed.urlListener = aUrlListener;
feed.folder = aFolder;
feed.msgWindow = aMsgWindow;
feed.folder = aFolder;
feed.msgWindow = aMsgWindow;
feed.download();
},
@ -166,17 +169,17 @@ var serializer = Components
// can access the Feed objects after it finishes downloading the feed files.
var gFzFeedCache = new Object();
function Feed(url, quickMode, title) {
this.url = url;
this.quickMode = quickMode || false;
this.title = title || null;
function Feed(resource) {
this.resource = resource.QueryInterface(Components.interfaces.nsIRDFResource);
this.description = null;
this.author = null;
this.description = null;
this.author = null;
this.request = null;
this.request = null;
return this;
this.items = new Array();
return this;
}
// The name of the message folder corresponding to the feed.
@ -245,6 +248,47 @@ Feed.onDownloadError = function(event) {
throw("error downloading feed " + url);
}
Feed.prototype.url getter = function() {
var ds = getSubscriptionsDS();
var url = ds.GetTarget(this.resource, DC_IDENTIFIER, true);
if (url)
url = url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
else
url = this.resource.Value;
return url;
}
Feed.prototype.title getter = function() {
var ds = getSubscriptionsDS();
var title = ds.GetTarget(this.resource, DC_TITLE, true);
if (title)
title = title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
return title;
}
Feed.prototype.title setter = function(new_title) {
var ds = getSubscriptionsDS();
new_title = rdf.GetLiteral(new_title || "");
var old_title = ds.GetTarget(this.resource, DC_TITLE, true);
if (old_title)
ds.Change(this.resource, DC_TITLE, old_title, new_title);
else
ds.Assert(this.resource, DC_TITLE, new_title, true);
}
Feed.prototype.quickMode getter = function() {
var ds = getSubscriptionsDS();
var quickMode = ds.GetTarget(this.resource, FZ_QUICKMODE, true);
if (quickMode) {
quickMode = quickMode.QueryInterface(Components.interfaces.nsIRDFLiteral);
quickMode = quickMode.Value;
quickMode = eval(quickMode);
}
return quickMode;
}
Feed.prototype.parse = function() {
// Figures out what description language (RSS, Atom) and version this feed
// is using and calls a language/version-specific feed parser.
@ -295,6 +339,8 @@ Feed.prototype.parseAsRSS2 = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var itemNodes = this.request.responseXML.getElementsByTagName("item");
for ( var i=0 ; i<itemNodes.length ; i++ ) {
var itemNode = itemNodes[i];
@ -326,7 +372,9 @@ Feed.prototype.parseAsRSS2 = function() {
|| item.date;
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.parseAsRSS1 = function() {
@ -346,6 +394,8 @@ Feed.prototype.parseAsRSS1 = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var items = ds.GetTarget(channel, RSS_ITEMS, true);
//items = items.QueryInterface(Components.interfaces.nsIRDFContainer);
items = rdfcontainer.MakeSeq(ds, items);
@ -380,7 +430,9 @@ Feed.prototype.parseAsRSS1 = function() {
item.content = getRDFTargetValue(ds, itemResource, RSS_CONTENT_ENCODED);
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.parseAsAtom = function() {
@ -398,6 +450,8 @@ Feed.prototype.parseAsAtom = function() {
if (!this.parseItems)
return;
this.invalidateItems();
var items = this.request.responseXML.getElementsByTagName("entry");
for ( var i=0 ; i<items.length ; i++ ) {
var itemNode = items[i];
@ -470,9 +524,46 @@ Feed.prototype.parseAsAtom = function() {
item.content = content;
item.store();
item.markValid();
}
this.removeInvalidItems();
}
Feed.prototype.invalidateItems = function invalidateItems() {
var ds = getItemsDS();
debug("invalidating items for " + this.url);
var items = ds.GetSources(FZ_FEED, this.resource, true);
var item;
while (items.hasMoreElements()) {
item = items.getNext();
item = item.QueryInterface(Components.interfaces.nsIRDFResource);
debug("invalidating " + item.Value);
var valid = ds.GetTarget(item, FZ_VALID, true);
if (valid)
ds.Unassert(item, FZ_VALID, valid, true);
}
}
Feed.prototype.removeInvalidItems = function() {
var ds = getItemsDS();
debug("removing invalid items for " + this.url);
var items = ds.GetSources(FZ_FEED, this.resource, true);
var item;
while (items.hasMoreElements()) {
item = items.getNext();
item = item.QueryInterface(Components.interfaces.nsIRDFResource);
if (ds.HasAssertion(item, FZ_VALID, RDF_LITERAL_TRUE, true))
continue;
debug("removing " + item.Value);
ds.Unassert(item, FZ_FEED, this.resource, true);
if (ds.hasArcOut(item, FZ_FEED))
debug(item.Value + " is from more than one feed; only the reference to this feed removed");
else
removeAssertions(ds, item);
}
}
// -----------------------------------------------
// From FeedItem.js
@ -646,7 +737,6 @@ FeedItem.prototype.store = function() {
content = content.replace(/%DESCRIPTION%/, this.description || this.title);
this.content = content; // XXX store it elsewhere, f.e. this.page
this.writeToFolder();
//this.download();
}
}
@ -674,22 +764,56 @@ FeedItem.prototype.isStored = function() {
return false;
}
try {
folder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
var db = folder.getMsgDatabase(this.feed.msgWindow);
var hdr = db.getMsgHdrForMessageID(this.messageID);
if (hdr) {
debug(this.identity + " stored");
return true;
var ds = getItemsDS();
var itemResource = rdf.GetResource(this.url || ("urn:" + this.id));
var downloaded = ds.GetTarget(itemResource, FZ_STORED, true);
if (!downloaded || downloaded.QueryInterface(Components.interfaces.nsIRDFLiteral).Value == "false")
{
debug(this.identity + " not stored");
return false;
}
else
{
debug(this.identity + " stored");
return true;
}
}
// XXX This should happen in the constructor automatically.
FeedItem.prototype.markValid = function() {
debug("validating " + this.url);
var ds = getItemsDS();
var resource = rdf.GetResource(this.url || ("urn:" + this.id));
if (!ds.HasAssertion(resource, FZ_FEED, rdf.GetResource(this.feed.url), true))
ds.Assert(resource, FZ_FEED, rdf.GetResource(this.feed.url), true);
if (ds.hasArcOut(resource, FZ_VALID)) {
var currentValue = ds.GetTarget(resource, FZ_VALID, true);
ds.Change(resource, FZ_VALID, currentValue, RDF_LITERAL_TRUE);
}
else {
return false;
ds.Assert(resource, FZ_VALID, RDF_LITERAL_TRUE, true);
}
}
FeedItem.prototype.markStored = function() {
var ds = getItemsDS();
var resource = rdf.GetResource(this.url || ("urn:" + this.id));
if (!ds.HasAssertion(resource, FZ_FEED, rdf.GetResource(this.feed.url), true))
ds.Assert(resource, FZ_FEED, rdf.GetResource(this.feed.url), true);
var currentValue;
if (ds.hasArcOut(resource, FZ_STORED)) {
currentValue = ds.GetTarget(resource, FZ_STORED, true);
ds.Change(resource, FZ_STORED, currentValue, RDF_LITERAL_TRUE);
}
else {
ds.Assert(resource, FZ_STORED, RDF_LITERAL_TRUE, true);
}
}
catch(e) {
debug(this.identity + " error checking if stored: " + e);
throw(e);
}
}
FeedItem.prototype.download = function() {
@ -797,6 +921,7 @@ FeedItem.prototype.writeToFolder = function() {
var folder = server.rootMsgFolder.getChildNamed(this.feed.name);
folder = folder.QueryInterface(Components.interfaces.nsIMsgLocalMailFolder);
folder.addMessage(source);
this.markStored();
}
function W3CToIETFDate(dateString) {
@ -1233,6 +1358,11 @@ const FZ_FEEDS = rdf.GetResource(FZ_NS + "feeds");
const FZ_FEED = rdf.GetResource(FZ_NS + "feed");
const FZ_QUICKMODE = rdf.GetResource(FZ_NS + "quickMode");
const FZ_DESTFOLDER = rdf.GetResource(FZ_NS + "destFolder");
const FZ_STORED = rdf.GetResource(FZ_NS + "stored");
const FZ_VALID = rdf.GetResource(FZ_NS + "valid");
const RDF_LITERAL_TRUE = rdf.GetLiteral("true");
const RDF_LITERAL_FALSE = rdf.GetLiteral("false");
// XXX There's a containerutils in forumzilla.js that this should be merged with.
var containerUtils =
@ -1347,3 +1477,71 @@ function createSubscriptionsFile(file) {
');
file.close();
}
var gFzItemsDS; // cache
function getItemsDS() {
if (gFzItemsDS)
return gFzItemsDS;
var file = getItemsFile();
var url = fileHandler.getURLSpecFromFile(file);
gFzItemsDS = rdf.GetDataSource(url);
if (!gFzItemsDS)
throw("can't get subscriptions data source");
// Note that it this point the datasource may not be loaded yet.
// You have to QueryInterface it to nsIRDFRemoteDataSource and check
// its "loaded" property to be sure. You can also attach an observer
// which will get notified when the load is complete.
return gFzItemsDS;
}
function getItemsFile() {
// Get the app directory service so we can look up the user's profile dir.
var appDirectoryService =
Components
.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
if ( !appDirectoryService )
throw("couldn't get the directory service");
// Get the user's profile directory.
var profileDir =
appDirectoryService.get("ProfD", Components.interfaces.nsIFile);
if ( !profileDir )
throw ("couldn't get the user's profile directory");
// Get the user's subscriptions file.
var file = profileDir.clone();
file.append("feeditems.rdf");
// If the file doesn't exist, create it.
if (!file.exists()) {
var newfile = new LocalFile(file, MODE_WRONLY | MODE_CREATE);
newfile.write('\
<?xml version="1.0"?>\n\
<RDF:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"\n\
xmlns:fz="' + FZ_NS + '"\n\
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n\
</RDF:RDF>\n\
');
newfile.close();
}
return file;
}
function removeAssertions(ds, resource) {
var properties = ds.ArcLabelsOut(resource);
var property;
while (properties.hasMoreElements()) {
property = properties.getNext();
var values = ds.GetTargets(resource, property, true);
var value;
while (values.hasMoreElements()) {
value = values.getNext();
ds.Unassert(resource, property, value, true);
}
}
}