summaryrefslogtreecommitdiffstats
path: root/rdf/datasource
diff options
context:
space:
mode:
Diffstat (limited to 'rdf/datasource')
-rw-r--r--rdf/datasource/moz.build22
-rw-r--r--rdf/datasource/nsFileSystemDataSource.cpp1328
-rw-r--r--rdf/datasource/nsFileSystemDataSource.h79
-rw-r--r--rdf/datasource/nsILocalStore.h34
-rw-r--r--rdf/datasource/nsIRDFFTP.h33
-rw-r--r--rdf/datasource/nsLocalStore.cpp481
-rw-r--r--rdf/datasource/nsRDFBuiltInDataSources.h27
7 files changed, 2004 insertions, 0 deletions
diff --git a/rdf/datasource/moz.build b/rdf/datasource/moz.build
new file mode 100644
index 000000000..5341562ff
--- /dev/null
+++ b/rdf/datasource/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS += [
+ 'nsILocalStore.h',
+]
+
+UNIFIED_SOURCES += [
+ 'nsFileSystemDataSource.cpp',
+ 'nsLocalStore.cpp',
+]
+
+FINAL_LIBRARY = 'xul'
+
+# "This is a dependency on rdfutil.h: it'll go away once that becomes
+# a first-class XPCOM interface."
+LOCAL_INCLUDES += [
+ '/rdf/base',
+]
diff --git a/rdf/datasource/nsFileSystemDataSource.cpp b/rdf/datasource/nsFileSystemDataSource.cpp
new file mode 100644
index 000000000..35632d1a3
--- /dev/null
+++ b/rdf/datasource/nsFileSystemDataSource.cpp
@@ -0,0 +1,1328 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ Implementation for a file system RDF data store.
+ */
+
+#include "nsFileSystemDataSource.h"
+
+#include <ctype.h> // for toupper()
+#include <stdio.h>
+#include "nsArrayEnumerator.h"
+#include "nsCOMArray.h"
+#include "nsIRDFDataSource.h"
+#include "nsIRDFObserver.h"
+#include "nsIServiceManager.h"
+#include "nsXPIDLString.h"
+#include "nsRDFCID.h"
+#include "rdfutil.h"
+#include "rdf.h"
+#include "nsEnumeratorUtils.h"
+#include "nsIURL.h"
+#include "nsIFileURL.h"
+#include "nsNetUtil.h"
+#include "nsIInputStream.h"
+#include "nsIChannel.h"
+#include "nsIFile.h"
+#include "nsEscape.h"
+#include "nsCRTGlue.h"
+#include "nsAutoPtr.h"
+#include "prtime.h"
+
+#ifdef XP_WIN
+#include "windef.h"
+#include "winbase.h"
+#include "nsILineInputStream.h"
+#include "nsDirectoryServiceDefs.h"
+#endif
+
+#define NS_MOZICON_SCHEME "moz-icon:"
+
+static const char kFileProtocol[] = "file://";
+
+bool
+FileSystemDataSource::isFileURI(nsIRDFResource *r)
+{
+ bool isFileURIFlag = false;
+ const char *uri = nullptr;
+
+ r->GetValueConst(&uri);
+ if ((uri) && (!strncmp(uri, kFileProtocol, sizeof(kFileProtocol) - 1)))
+ {
+ // XXX HACK HACK HACK
+ if (!strchr(uri, '#'))
+ {
+ isFileURIFlag = true;
+ }
+ }
+ return(isFileURIFlag);
+}
+
+
+
+bool
+FileSystemDataSource::isDirURI(nsIRDFResource* source)
+{
+ nsresult rv;
+ const char *uri = nullptr;
+
+ rv = source->GetValueConst(&uri);
+ if (NS_FAILED(rv)) return(false);
+
+ nsCOMPtr<nsIFile> aDir;
+
+ rv = NS_GetFileFromURLSpec(nsDependentCString(uri), getter_AddRefs(aDir));
+ if (NS_FAILED(rv)) return(false);
+
+ bool isDirFlag = false;
+
+ rv = aDir->IsDirectory(&isDirFlag);
+ if (NS_FAILED(rv)) return(false);
+
+ return(isDirFlag);
+}
+
+
+nsresult
+FileSystemDataSource::Init()
+{
+ nsresult rv;
+
+ mRDFService = do_GetService("@mozilla.org/rdf/rdf-service;1");
+ NS_ENSURE_TRUE(mRDFService, NS_ERROR_FAILURE);
+
+ rv = mRDFService->GetResource(NS_LITERAL_CSTRING("NC:FilesRoot"),
+ getter_AddRefs(mNC_FileSystemRoot));
+ nsresult tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
+ getter_AddRefs(mNC_Child));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
+ getter_AddRefs(mNC_Name));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
+ getter_AddRefs(mNC_URL));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Icon"),
+ getter_AddRefs(mNC_Icon));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"),
+ getter_AddRefs(mNC_Length));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsDirectory"),
+ getter_AddRefs(mNC_IsDirectory));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
+ getter_AddRefs(mWEB_LastMod));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "FileSystemObject"),
+ getter_AddRefs(mNC_FileSystemObject));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "pulse"),
+ getter_AddRefs(mNC_pulse));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
+ getter_AddRefs(mRDF_InstanceOf));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
+ getter_AddRefs(mRDF_type));
+
+ static const char16_t kTrue[] = {'t','r','u','e','\0'};
+ static const char16_t kFalse[] = {'f','a','l','s','e','\0'};
+
+ tmp = mRDFService->GetLiteral(kTrue, getter_AddRefs(mLiteralTrue));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = mRDFService->GetLiteral(kFalse, getter_AddRefs(mLiteralFalse));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+#ifdef USE_NC_EXTENSION
+ rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "extension"),
+ getter_AddRefs(mNC_extension));
+ NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
+#ifdef XP_WIN
+ rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavorite"),
+ getter_AddRefs(mNC_IEFavoriteObject));
+ tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavoriteFolder"),
+ getter_AddRefs(mNC_IEFavoriteFolder));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIFile> file;
+ NS_GetSpecialDirectory(NS_WIN_FAVORITES_DIR, getter_AddRefs(file));
+ if (file)
+ {
+ nsCOMPtr<nsIURI> furi;
+ NS_NewFileURI(getter_AddRefs(furi), file);
+ NS_ENSURE_TRUE(furi, NS_ERROR_FAILURE);
+
+ file->GetNativePath(ieFavoritesDir);
+ }
+#endif
+
+ return NS_OK;
+}
+
+//static
+nsresult
+FileSystemDataSource::Create(nsISupports* aOuter, const nsIID& aIID, void **aResult)
+{
+ NS_ENSURE_NO_AGGREGATION(aOuter);
+
+ RefPtr<FileSystemDataSource> self = new FileSystemDataSource();
+ if (!self)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = self->Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return self->QueryInterface(aIID, aResult);
+}
+
+NS_IMPL_ISUPPORTS(FileSystemDataSource, nsIRDFDataSource)
+
+NS_IMETHODIMP
+FileSystemDataSource::GetURI(char **uri)
+{
+ NS_PRECONDITION(uri != nullptr, "null ptr");
+ if (! uri)
+ return NS_ERROR_NULL_POINTER;
+
+ if ((*uri = NS_strdup("rdf:files")) == nullptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetSource(nsIRDFResource* property,
+ nsIRDFNode* target,
+ bool tv,
+ nsIRDFResource** source /* out */)
+{
+ NS_PRECONDITION(property != nullptr, "null ptr");
+ if (! property)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(target != nullptr, "null ptr");
+ if (! target)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(source != nullptr, "null ptr");
+ if (! source)
+ return NS_ERROR_NULL_POINTER;
+
+ *source = nullptr;
+ return NS_RDF_NO_VALUE;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetSources(nsIRDFResource *property,
+ nsIRDFNode *target,
+ bool tv,
+ nsISimpleEnumerator **sources /* out */)
+{
+// NS_NOTYETIMPLEMENTED("write me");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetTarget(nsIRDFResource *source,
+ nsIRDFResource *property,
+ bool tv,
+ nsIRDFNode **target /* out */)
+{
+ NS_PRECONDITION(source != nullptr, "null ptr");
+ if (! source)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(property != nullptr, "null ptr");
+ if (! property)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(target != nullptr, "null ptr");
+ if (! target)
+ return NS_ERROR_NULL_POINTER;
+
+ *target = nullptr;
+
+ nsresult rv = NS_RDF_NO_VALUE;
+
+ // we only have positive assertions in the file system data source.
+ if (! tv)
+ return NS_RDF_NO_VALUE;
+
+ if (source == mNC_FileSystemRoot)
+ {
+ if (property == mNC_pulse)
+ {
+ nsIRDFLiteral *pulseLiteral;
+ mRDFService->GetLiteral(u"12", &pulseLiteral);
+ *target = pulseLiteral;
+ return NS_OK;
+ }
+ }
+ else if (isFileURI(source))
+ {
+ if (property == mNC_Name)
+ {
+ nsCOMPtr<nsIRDFLiteral> name;
+ rv = GetName(source, getter_AddRefs(name));
+ if (NS_FAILED(rv)) return(rv);
+ if (!name) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+ return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ else if (property == mNC_URL)
+ {
+ nsCOMPtr<nsIRDFLiteral> url;
+ rv = GetURL(source, nullptr, getter_AddRefs(url));
+ if (NS_FAILED(rv)) return(rv);
+ if (!url) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+
+ return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ else if (property == mNC_Icon)
+ {
+ nsCOMPtr<nsIRDFLiteral> url;
+ bool isFavorite = false;
+ rv = GetURL(source, &isFavorite, getter_AddRefs(url));
+ if (NS_FAILED(rv)) return(rv);
+ if (isFavorite || !url) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+
+ const char16_t *uni = nullptr;
+ url->GetValueConst(&uni);
+ if (!uni) return(NS_RDF_NO_VALUE);
+ nsAutoString urlStr;
+ urlStr.AssignLiteral(NS_MOZICON_SCHEME);
+ urlStr.Append(uni);
+
+ rv = mRDFService->GetLiteral(urlStr.get(), getter_AddRefs(url));
+ if (NS_FAILED(rv) || !url) return(NS_RDF_NO_VALUE);
+ return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ else if (property == mNC_Length)
+ {
+ nsCOMPtr<nsIRDFInt> fileSize;
+ rv = GetFileSize(source, getter_AddRefs(fileSize));
+ if (NS_FAILED(rv)) return(rv);
+ if (!fileSize) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+
+ return fileSize->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ else if (property == mNC_IsDirectory)
+ {
+ *target = (isDirURI(source)) ? mLiteralTrue : mLiteralFalse;
+ NS_ADDREF(*target);
+ return NS_OK;
+ }
+ else if (property == mWEB_LastMod)
+ {
+ nsCOMPtr<nsIRDFDate> lastMod;
+ rv = GetLastMod(source, getter_AddRefs(lastMod));
+ if (NS_FAILED(rv)) return(rv);
+ if (!lastMod) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+
+ return lastMod->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ else if (property == mRDF_type)
+ {
+ nsCString type;
+ rv = mNC_FileSystemObject->GetValueUTF8(type);
+ if (NS_FAILED(rv)) return(rv);
+
+#ifdef XP_WIN
+ // under Windows, if its an IE favorite, return that type
+ if (!ieFavoritesDir.IsEmpty())
+ {
+ nsCString uri;
+ rv = source->GetValueUTF8(uri);
+ if (NS_FAILED(rv)) return(rv);
+
+ NS_ConvertUTF8toUTF16 theURI(uri);
+
+ if (theURI.Find(ieFavoritesDir) == 0)
+ {
+ if (theURI[theURI.Length() - 1] == '/')
+ {
+ rv = mNC_IEFavoriteFolder->GetValueUTF8(type);
+ }
+ else
+ {
+ rv = mNC_IEFavoriteObject->GetValueUTF8(type);
+ }
+ if (NS_FAILED(rv)) return(rv);
+ }
+ }
+#endif
+
+ NS_ConvertUTF8toUTF16 url(type);
+ nsCOMPtr<nsIRDFLiteral> literal;
+ mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
+ rv = literal->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ return(rv);
+ }
+ else if (property == mNC_pulse)
+ {
+ nsCOMPtr<nsIRDFLiteral> pulseLiteral;
+ mRDFService->GetLiteral(u"12", getter_AddRefs(pulseLiteral));
+ rv = pulseLiteral->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ return(rv);
+ }
+ else if (property == mNC_Child)
+ {
+ // Oh this is evil. Somebody kill me now.
+ nsCOMPtr<nsISimpleEnumerator> children;
+ rv = GetFolderList(source, false, true, getter_AddRefs(children));
+ if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE)) return(rv);
+
+ bool hasMore;
+ rv = children->HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return(rv);
+
+ if (hasMore)
+ {
+ nsCOMPtr<nsISupports> isupports;
+ rv = children->GetNext(getter_AddRefs(isupports));
+ if (NS_FAILED(rv)) return(rv);
+
+ return isupports->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+ }
+#ifdef USE_NC_EXTENSION
+ else if (property == mNC_extension)
+ {
+ nsCOMPtr<nsIRDFLiteral> extension;
+ rv = GetExtension(source, getter_AddRefs(extension));
+ if (!extension) rv = NS_RDF_NO_VALUE;
+ if (rv == NS_RDF_NO_VALUE) return(rv);
+ return extension->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
+ }
+#endif
+ }
+
+ return(NS_RDF_NO_VALUE);
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetTargets(nsIRDFResource *source,
+ nsIRDFResource *property,
+ bool tv,
+ nsISimpleEnumerator **targets /* out */)
+{
+ NS_PRECONDITION(source != nullptr, "null ptr");
+ if (! source)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(property != nullptr, "null ptr");
+ if (! property)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(targets != nullptr, "null ptr");
+ if (! targets)
+ return NS_ERROR_NULL_POINTER;
+
+ *targets = nullptr;
+
+ // we only have positive assertions in the file system data source.
+ if (! tv)
+ return NS_RDF_NO_VALUE;
+
+ nsresult rv;
+
+ if (source == mNC_FileSystemRoot)
+ {
+ if (property == mNC_Child)
+ {
+ return GetVolumeList(targets);
+ }
+ else if (property == mNC_pulse)
+ {
+ nsCOMPtr<nsIRDFLiteral> pulseLiteral;
+ mRDFService->GetLiteral(u"12",
+ getter_AddRefs(pulseLiteral));
+ return NS_NewSingletonEnumerator(targets, pulseLiteral);
+ }
+ }
+ else if (isFileURI(source))
+ {
+ if (property == mNC_Child)
+ {
+ return GetFolderList(source, false, false, targets);
+ }
+ else if (property == mNC_Name)
+ {
+ nsCOMPtr<nsIRDFLiteral> name;
+ rv = GetName(source, getter_AddRefs(name));
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_NewSingletonEnumerator(targets, name);
+ }
+ else if (property == mNC_URL)
+ {
+ nsCOMPtr<nsIRDFLiteral> url;
+ rv = GetURL(source, nullptr, getter_AddRefs(url));
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_NewSingletonEnumerator(targets, url);
+ }
+ else if (property == mRDF_type)
+ {
+ nsCString uri;
+ rv = mNC_FileSystemObject->GetValueUTF8(uri);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ConvertUTF8toUTF16 url(uri);
+
+ nsCOMPtr<nsIRDFLiteral> literal;
+ rv = mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_NewSingletonEnumerator(targets, literal);
+ }
+ else if (property == mNC_pulse)
+ {
+ nsCOMPtr<nsIRDFLiteral> pulseLiteral;
+ rv = mRDFService->GetLiteral(u"12",
+ getter_AddRefs(pulseLiteral));
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_NewSingletonEnumerator(targets, pulseLiteral);
+ }
+ }
+
+ return NS_NewEmptyEnumerator(targets);
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::Assert(nsIRDFResource *source,
+ nsIRDFResource *property,
+ nsIRDFNode *target,
+ bool tv)
+{
+ return NS_RDF_ASSERTION_REJECTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::Unassert(nsIRDFResource *source,
+ nsIRDFResource *property,
+ nsIRDFNode *target)
+{
+ return NS_RDF_ASSERTION_REJECTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::Change(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aOldTarget,
+ nsIRDFNode* aNewTarget)
+{
+ return NS_RDF_ASSERTION_REJECTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::Move(nsIRDFResource* aOldSource,
+ nsIRDFResource* aNewSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget)
+{
+ return NS_RDF_ASSERTION_REJECTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::HasAssertion(nsIRDFResource *source,
+ nsIRDFResource *property,
+ nsIRDFNode *target,
+ bool tv,
+ bool *hasAssertion /* out */)
+{
+ NS_PRECONDITION(source != nullptr, "null ptr");
+ if (! source)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(property != nullptr, "null ptr");
+ if (! property)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(target != nullptr, "null ptr");
+ if (! target)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(hasAssertion != nullptr, "null ptr");
+ if (! hasAssertion)
+ return NS_ERROR_NULL_POINTER;
+
+ // we only have positive assertions in the file system data source.
+ *hasAssertion = false;
+
+ if (! tv) {
+ return NS_OK;
+ }
+
+ if ((source == mNC_FileSystemRoot) || isFileURI(source))
+ {
+ if (property == mRDF_type)
+ {
+ nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(target) );
+ if (resource.get() == mRDF_type)
+ {
+ *hasAssertion = true;
+ }
+ }
+#ifdef USE_NC_EXTENSION
+ else if (property == mNC_extension)
+ {
+ // Cheat just a little here by making dirs always match
+ if (isDirURI(source))
+ {
+ *hasAssertion = true;
+ }
+ else
+ {
+ nsCOMPtr<nsIRDFLiteral> extension;
+ GetExtension(source, getter_AddRefs(extension));
+ if (extension.get() == target)
+ {
+ *hasAssertion = true;
+ }
+ }
+ }
+#endif
+ else if (property == mNC_IsDirectory)
+ {
+ bool isDir = isDirURI(source);
+ bool isEqual = false;
+ target->EqualsNode(mLiteralTrue, &isEqual);
+ if (isEqual)
+ {
+ *hasAssertion = isDir;
+ }
+ else
+ {
+ target->EqualsNode(mLiteralFalse, &isEqual);
+ if (isEqual)
+ *hasAssertion = !isDir;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
+{
+ *result = false;
+
+ if (aSource == mNC_FileSystemRoot)
+ {
+ *result = (aArc == mNC_Child || aArc == mNC_pulse);
+ }
+ else if (isFileURI(aSource))
+ {
+ if (aArc == mNC_pulse)
+ {
+ *result = true;
+ }
+ else if (isDirURI(aSource))
+ {
+#ifdef XP_WIN
+ *result = isValidFolder(aSource);
+#else
+ *result = true;
+#endif
+ }
+ else if (aArc == mNC_pulse || aArc == mNC_Name || aArc == mNC_Icon ||
+ aArc == mNC_URL || aArc == mNC_Length || aArc == mWEB_LastMod ||
+ aArc == mNC_FileSystemObject || aArc == mRDF_InstanceOf ||
+ aArc == mRDF_type)
+ {
+ *result = true;
+ }
+ }
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::ArcLabelsIn(nsIRDFNode *node,
+ nsISimpleEnumerator ** labels /* out */)
+{
+// NS_NOTYETIMPLEMENTED("write me");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::ArcLabelsOut(nsIRDFResource *source,
+ nsISimpleEnumerator **labels /* out */)
+{
+ NS_PRECONDITION(source != nullptr, "null ptr");
+ if (! source)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(labels != nullptr, "null ptr");
+ if (! labels)
+ return NS_ERROR_NULL_POINTER;
+
+ if (source == mNC_FileSystemRoot)
+ {
+ nsCOMArray<nsIRDFResource> resources;
+ resources.SetCapacity(2);
+
+ resources.AppendObject(mNC_Child);
+ resources.AppendObject(mNC_pulse);
+
+ return NS_NewArrayEnumerator(labels, resources);
+ }
+ else if (isFileURI(source))
+ {
+ nsCOMArray<nsIRDFResource> resources;
+ resources.SetCapacity(2);
+
+ if (isDirURI(source))
+ {
+#ifdef XP_WIN
+ if (isValidFolder(source))
+ {
+ resources.AppendObject(mNC_Child);
+ }
+#else
+ resources.AppendObject(mNC_Child);
+#endif
+ resources.AppendObject(mNC_pulse);
+ }
+
+ return NS_NewArrayEnumerator(labels, resources);
+ }
+
+ return NS_NewEmptyEnumerator(labels);
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
+{
+ NS_NOTYETIMPLEMENTED("sorry!");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::AddObserver(nsIRDFObserver *n)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::RemoveObserver(nsIRDFObserver *n)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::GetAllCmds(nsIRDFResource* source,
+ nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
+{
+ return(NS_NewEmptyEnumerator(commands));
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::IsCommandEnabled(nsISupports/*<nsIRDFResource>*/* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports/*<nsIRDFResource>*/* aArguments,
+ bool* aResult)
+{
+ return(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::DoCommand(nsISupports/*<nsIRDFResource>*/* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports/*<nsIRDFResource>*/* aArguments)
+{
+ return(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::BeginUpdateBatch()
+{
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+FileSystemDataSource::EndUpdateBatch()
+{
+ return NS_OK;
+}
+
+
+
+nsresult
+FileSystemDataSource::GetVolumeList(nsISimpleEnumerator** aResult)
+{
+ nsCOMArray<nsIRDFResource> volumes;
+ nsCOMPtr<nsIRDFResource> vol;
+
+#ifdef XP_WIN
+
+ int32_t driveType;
+ wchar_t drive[32];
+ int32_t volNum;
+
+ for (volNum = 0; volNum < 26; volNum++)
+ {
+ swprintf_s(drive, 32, L"%c:\\", volNum + (char16_t)'A');
+
+ driveType = GetDriveTypeW(drive);
+ if (driveType != DRIVE_UNKNOWN && driveType != DRIVE_NO_ROOT_DIR)
+ {
+ nsAutoCString url;
+ url.AppendPrintf("file:///%c|/", volNum + 'A');
+ nsresult rv = mRDFService->GetResource(url, getter_AddRefs(vol));
+ if (NS_FAILED(rv))
+ return rv;
+
+ volumes.AppendObject(vol);
+ }
+ }
+#endif
+
+#ifdef XP_UNIX
+ mRDFService->GetResource(NS_LITERAL_CSTRING("file:///"), getter_AddRefs(vol));
+ volumes.AppendObject(vol);
+#endif
+
+ return NS_NewArrayEnumerator(aResult, volumes);
+}
+
+
+
+#ifdef XP_WIN
+bool
+FileSystemDataSource::isValidFolder(nsIRDFResource *source)
+{
+ bool isValid = true;
+ if (ieFavoritesDir.IsEmpty()) return(isValid);
+
+ nsresult rv;
+ nsCString uri;
+ rv = source->GetValueUTF8(uri);
+ if (NS_FAILED(rv)) return(isValid);
+
+ NS_ConvertUTF8toUTF16 theURI(uri);
+ if (theURI.Find(ieFavoritesDir) == 0)
+ {
+ isValid = false;
+
+ nsCOMPtr<nsISimpleEnumerator> folderEnum;
+ if (NS_SUCCEEDED(rv = GetFolderList(source, true, false, getter_AddRefs(folderEnum))))
+ {
+ bool hasAny = false, hasMore;
+ while (NS_SUCCEEDED(folderEnum->HasMoreElements(&hasMore)) &&
+ hasMore)
+ {
+ hasAny = true;
+
+ nsCOMPtr<nsISupports> isupports;
+ if (NS_FAILED(rv = folderEnum->GetNext(getter_AddRefs(isupports))))
+ break;
+ nsCOMPtr<nsIRDFResource> res = do_QueryInterface(isupports);
+ if (!res) break;
+
+ nsCOMPtr<nsIRDFLiteral> nameLiteral;
+ if (NS_FAILED(rv = GetName(res, getter_AddRefs(nameLiteral))))
+ break;
+
+ const char16_t *uniName;
+ if (NS_FAILED(rv = nameLiteral->GetValueConst(&uniName)))
+ break;
+ nsAutoString name(uniName);
+
+ // An empty folder, or a folder that contains just "desktop.ini",
+ // is considered to be a IE Favorite; otherwise, its a folder
+ if (!name.LowerCaseEqualsLiteral("desktop.ini"))
+ {
+ isValid = true;
+ break;
+ }
+ }
+ if (!hasAny) isValid = true;
+ }
+ }
+ return(isValid);
+}
+#endif
+
+
+
+nsresult
+FileSystemDataSource::GetFolderList(nsIRDFResource *source, bool allowHidden,
+ bool onlyFirst, nsISimpleEnumerator** aResult)
+{
+ if (!isDirURI(source))
+ return(NS_RDF_NO_VALUE);
+
+ nsresult rv;
+
+ const char *parentURI = nullptr;
+ rv = source->GetValueConst(&parentURI);
+ if (NS_FAILED(rv))
+ return(rv);
+ if (!parentURI)
+ return(NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIURI> aIURI;
+ if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(parentURI))))
+ return(rv);
+
+ nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
+ if (!fileURL)
+ return NS_OK;
+
+ nsCOMPtr<nsIFile> aDir;
+ if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aDir))))
+ return(rv);
+
+ // ensure that we DO NOT resolve aliases
+ aDir->SetFollowLinks(false);
+
+ nsCOMPtr<nsISimpleEnumerator> dirContents;
+ if (NS_FAILED(rv = aDir->GetDirectoryEntries(getter_AddRefs(dirContents))))
+ return(rv);
+ if (!dirContents)
+ return(NS_ERROR_UNEXPECTED);
+
+ nsCOMArray<nsIRDFResource> resources;
+ bool hasMore;
+ while(NS_SUCCEEDED(rv = dirContents->HasMoreElements(&hasMore)) &&
+ hasMore)
+ {
+ nsCOMPtr<nsISupports> isupports;
+ if (NS_FAILED(rv = dirContents->GetNext(getter_AddRefs(isupports))))
+ break;
+
+ nsCOMPtr<nsIFile> aFile = do_QueryInterface(isupports);
+ if (!aFile)
+ break;
+
+ if (!allowHidden)
+ {
+ bool hiddenFlag = false;
+ if (NS_FAILED(rv = aFile->IsHidden(&hiddenFlag)))
+ break;
+ if (hiddenFlag)
+ continue;
+ }
+
+ nsAutoString leafStr;
+ if (NS_FAILED(rv = aFile->GetLeafName(leafStr)))
+ break;
+ if (leafStr.IsEmpty())
+ continue;
+
+ nsAutoCString fullURI;
+ fullURI.Assign(parentURI);
+ if (fullURI.Last() != '/')
+ {
+ fullURI.Append('/');
+ }
+
+ nsAutoCString leaf;
+ bool escaped = NS_Escape(NS_ConvertUTF16toUTF8(leafStr), leaf, url_Path);
+ leafStr.Truncate();
+
+ if (!escaped) {
+ continue;
+ }
+
+ // using nsEscape() [above] doesn't escape slashes, so do that by hand
+ int32_t aOffset;
+ while ((aOffset = leaf.FindChar('/')) >= 0)
+ {
+ leaf.Cut((uint32_t)aOffset, 1);
+ leaf.Insert("%2F", (uint32_t)aOffset);
+ }
+
+ // append the encoded name
+ fullURI.Append(leaf);
+
+ bool dirFlag = false;
+ rv = aFile->IsDirectory(&dirFlag);
+ if (NS_SUCCEEDED(rv) && dirFlag)
+ {
+ fullURI.Append('/');
+ }
+
+ nsCOMPtr<nsIRDFResource> fileRes;
+ mRDFService->GetResource(fullURI, getter_AddRefs(fileRes));
+
+ resources.AppendObject(fileRes);
+
+ if (onlyFirst)
+ break;
+ }
+
+ return NS_NewArrayEnumerator(aResult, resources);
+}
+
+nsresult
+FileSystemDataSource::GetLastMod(nsIRDFResource *source, nsIRDFDate **aResult)
+{
+ *aResult = nullptr;
+
+ nsresult rv;
+ const char *uri = nullptr;
+
+ rv = source->GetValueConst(&uri);
+ if (NS_FAILED(rv)) return(rv);
+ if (!uri)
+ return(NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIURI> aIURI;
+ if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
+ return(rv);
+
+ nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
+ if (!fileURL)
+ return NS_OK;
+
+ nsCOMPtr<nsIFile> aFile;
+ if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
+ return(rv);
+ if (!aFile)
+ return(NS_ERROR_UNEXPECTED);
+
+ // ensure that we DO NOT resolve aliases
+ aFile->SetFollowLinks(false);
+
+ PRTime lastModDate;
+ if (NS_FAILED(rv = aFile->GetLastModifiedTime(&lastModDate)))
+ return(rv);
+
+ // convert from milliseconds to seconds
+ mRDFService->GetDateLiteral(lastModDate * PR_MSEC_PER_SEC, aResult);
+
+ return(NS_OK);
+}
+
+
+
+nsresult
+FileSystemDataSource::GetFileSize(nsIRDFResource *source, nsIRDFInt **aResult)
+{
+ *aResult = nullptr;
+
+ nsresult rv;
+ const char *uri = nullptr;
+
+ rv = source->GetValueConst(&uri);
+ if (NS_FAILED(rv))
+ return(rv);
+ if (!uri)
+ return(NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIURI> aIURI;
+ if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
+ return(rv);
+
+ nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
+ if (!fileURL)
+ return NS_OK;
+
+ nsCOMPtr<nsIFile> aFile;
+ if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
+ return(rv);
+ if (!aFile)
+ return(NS_ERROR_UNEXPECTED);
+
+ // ensure that we DO NOT resolve aliases
+ aFile->SetFollowLinks(false);
+
+ // don't do anything with directories
+ bool isDir = false;
+ if (NS_FAILED(rv = aFile->IsDirectory(&isDir)))
+ return(rv);
+ if (isDir)
+ return(NS_RDF_NO_VALUE);
+
+ int64_t aFileSize64;
+ if (NS_FAILED(rv = aFile->GetFileSize(&aFileSize64)))
+ return(rv);
+
+ // convert 64bits to 32bits
+ int32_t aFileSize32 = int32_t(aFileSize64);
+ mRDFService->GetIntLiteral(aFileSize32, aResult);
+
+ return(NS_OK);
+}
+
+
+
+nsresult
+FileSystemDataSource::GetName(nsIRDFResource *source, nsIRDFLiteral **aResult)
+{
+ nsresult rv;
+ const char *uri = nullptr;
+
+ rv = source->GetValueConst(&uri);
+ if (NS_FAILED(rv))
+ return(rv);
+ if (!uri)
+ return(NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIURI> aIURI;
+ if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
+ return(rv);
+
+ nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
+ if (!fileURL)
+ return NS_OK;
+
+ nsCOMPtr<nsIFile> aFile;
+ if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
+ return(rv);
+ if (!aFile)
+ return(NS_ERROR_UNEXPECTED);
+
+ // ensure that we DO NOT resolve aliases
+ aFile->SetFollowLinks(false);
+
+ nsAutoString name;
+ if (NS_FAILED(rv = aFile->GetLeafName(name)))
+ return(rv);
+ if (name.IsEmpty())
+ return(NS_ERROR_UNEXPECTED);
+
+#ifdef XP_WIN
+ // special hack for IE favorites under Windows; strip off the
+ // trailing ".url" or ".lnk" at the end of IE favorites names
+ int32_t nameLen = name.Length();
+ if ((strncmp(uri, ieFavoritesDir.get(), ieFavoritesDir.Length()) == 0) && (nameLen > 4))
+ {
+ nsAutoString extension;
+ name.Right(extension, 4);
+ if (extension.LowerCaseEqualsLiteral(".url") ||
+ extension.LowerCaseEqualsLiteral(".lnk"))
+ {
+ name.Truncate(nameLen - 4);
+ }
+ }
+#endif
+
+ mRDFService->GetLiteral(name.get(), aResult);
+
+ return NS_OK;
+}
+
+
+
+#ifdef USE_NC_EXTENSION
+nsresult
+FileSystemDataSource::GetExtension(nsIRDFResource *source, nsIRDFLiteral **aResult)
+{
+ nsCOMPtr<nsIRDFLiteral> name;
+ nsresult rv = GetName(source, getter_AddRefs(name));
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char16_t* unicodeLeafName;
+ rv = name->GetValueConst(&unicodeLeafName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoString filename(unicodeLeafName);
+ int32_t lastDot = filename.RFindChar('.');
+ if (lastDot == -1)
+ {
+ mRDFService->GetLiteral(EmptyString().get(), aResult);
+ }
+ else
+ {
+ nsAutoString extension;
+ filename.Right(extension, (filename.Length() - lastDot));
+ mRDFService->GetLiteral(extension.get(), aResult);
+ }
+
+ return NS_OK;
+}
+#endif
+
+#ifdef XP_WIN
+nsresult
+FileSystemDataSource::getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral)
+{
+ nsresult rv = NS_OK;
+
+ *urlLiteral = nullptr;
+
+ nsCOMPtr<nsIFile> f;
+ NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileURL), getter_AddRefs(f));
+
+ bool value;
+
+ if (NS_SUCCEEDED(f->IsDirectory(&value)) && value)
+ {
+ if (isValidFolder(source))
+ return(NS_RDF_NO_VALUE);
+ aFileURL.AppendLiteral("desktop.ini");
+ }
+ else if (aFileURL.Length() > 4)
+ {
+ nsAutoString extension;
+
+ aFileURL.Right(extension, 4);
+ if (!extension.LowerCaseEqualsLiteral(".url"))
+ {
+ return(NS_RDF_NO_VALUE);
+ }
+ }
+
+ nsCOMPtr<nsIInputStream> strm;
+ NS_NewLocalFileInputStream(getter_AddRefs(strm),f);
+ nsCOMPtr<nsILineInputStream> linereader = do_QueryInterface(strm, &rv);
+
+ nsAutoString line;
+ nsAutoCString cLine;
+ while(NS_SUCCEEDED(rv))
+ {
+ bool isEOF;
+ rv = linereader->ReadLine(cLine, &isEOF);
+ CopyASCIItoUTF16(cLine, line);
+
+ if (isEOF)
+ {
+ if (line.Find("URL=", true) == 0)
+ {
+ line.Cut(0, 4);
+ rv = mRDFService->GetLiteral(line.get(), urlLiteral);
+ break;
+ }
+ else if (line.Find("CDFURL=", true) == 0)
+ {
+ line.Cut(0, 7);
+ rv = mRDFService->GetLiteral(line.get(), urlLiteral);
+ break;
+ }
+ line.Truncate();
+ }
+ }
+
+ return(rv);
+}
+#endif
+
+
+
+nsresult
+FileSystemDataSource::GetURL(nsIRDFResource *source, bool *isFavorite, nsIRDFLiteral** aResult)
+{
+ if (isFavorite) *isFavorite = false;
+
+ nsresult rv;
+ nsCString uri;
+
+ rv = source->GetValueUTF8(uri);
+ if (NS_FAILED(rv))
+ return(rv);
+
+ NS_ConvertUTF8toUTF16 url(uri);
+
+#ifdef XP_WIN
+ // under Windows, if its an IE favorite, munge the URL
+ if (!ieFavoritesDir.IsEmpty())
+ {
+ if (url.Find(ieFavoritesDir) == 0)
+ {
+ if (isFavorite) *isFavorite = true;
+ rv = getIEFavoriteURL(source, url, aResult);
+ return(rv);
+ }
+ }
+#endif
+
+ // if we fall through to here, its not any type of bookmark
+ // stored in the platform native file system, so just set the URL
+
+ mRDFService->GetLiteral(url.get(), aResult);
+
+ return(NS_OK);
+}
diff --git a/rdf/datasource/nsFileSystemDataSource.h b/rdf/datasource/nsFileSystemDataSource.h
new file mode 100644
index 000000000..09fa17400
--- /dev/null
+++ b/rdf/datasource/nsFileSystemDataSource.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#ifndef nsFileSystemDataSource_h__
+#define nsFileSystemDataSource_h__
+
+#include "nsIRDFDataSource.h"
+#include "nsIRDFLiteral.h"
+#include "nsIRDFResource.h"
+#include "nsIRDFService.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "mozilla/Attributes.h"
+
+#if defined(XP_UNIX) || defined(XP_WIN)
+#define USE_NC_EXTENSION
+#endif
+
+class FileSystemDataSource final : public nsIRDFDataSource
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRDFDATASOURCE
+
+ static nsresult Create(nsISupports* aOuter,
+ const nsIID& aIID, void **aResult);
+
+ nsresult Init();
+
+private:
+ FileSystemDataSource() { }
+ ~FileSystemDataSource() { }
+
+ // helper methods
+ bool isFileURI(nsIRDFResource* aResource);
+ bool isDirURI(nsIRDFResource* aSource);
+ nsresult GetVolumeList(nsISimpleEnumerator **aResult);
+ nsresult GetFolderList(nsIRDFResource *source, bool allowHidden, bool onlyFirst, nsISimpleEnumerator **aResult);
+ nsresult GetName(nsIRDFResource *source, nsIRDFLiteral** aResult);
+ nsresult GetURL(nsIRDFResource *source, bool *isFavorite, nsIRDFLiteral** aResult);
+ nsresult GetFileSize(nsIRDFResource *source, nsIRDFInt** aResult);
+ nsresult GetLastMod(nsIRDFResource *source, nsIRDFDate** aResult);
+
+ nsCOMPtr<nsIRDFService> mRDFService;
+
+ // pseudo-constants
+ nsCOMPtr<nsIRDFResource> mNC_FileSystemRoot;
+ nsCOMPtr<nsIRDFResource> mNC_Child;
+ nsCOMPtr<nsIRDFResource> mNC_Name;
+ nsCOMPtr<nsIRDFResource> mNC_URL;
+ nsCOMPtr<nsIRDFResource> mNC_Icon;
+ nsCOMPtr<nsIRDFResource> mNC_Length;
+ nsCOMPtr<nsIRDFResource> mNC_IsDirectory;
+ nsCOMPtr<nsIRDFResource> mWEB_LastMod;
+ nsCOMPtr<nsIRDFResource> mNC_FileSystemObject;
+ nsCOMPtr<nsIRDFResource> mNC_pulse;
+ nsCOMPtr<nsIRDFResource> mRDF_InstanceOf;
+ nsCOMPtr<nsIRDFResource> mRDF_type;
+
+ nsCOMPtr<nsIRDFLiteral> mLiteralTrue;
+ nsCOMPtr<nsIRDFLiteral> mLiteralFalse;
+
+#ifdef USE_NC_EXTENSION
+ nsresult GetExtension(nsIRDFResource *source, nsIRDFLiteral** aResult);
+ nsCOMPtr<nsIRDFResource> mNC_extension;
+#endif
+
+#ifdef XP_WIN
+ bool isValidFolder(nsIRDFResource *source);
+ nsresult getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral);
+ nsCOMPtr<nsIRDFResource> mNC_IEFavoriteObject;
+ nsCOMPtr<nsIRDFResource> mNC_IEFavoriteFolder;
+ nsCString ieFavoritesDir;
+#endif
+};
+
+#endif // nsFileSystemDataSource_h__
diff --git a/rdf/datasource/nsILocalStore.h b/rdf/datasource/nsILocalStore.h
new file mode 100644
index 000000000..b41226593
--- /dev/null
+++ b/rdf/datasource/nsILocalStore.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#ifndef nsILocalStore_h__
+#define nsILocalStore_h__
+
+#include "rdf.h"
+#include "nsISupports.h"
+
+// {DF71C6F1-EC53-11d2-BDCA-000064657374}
+#define NS_ILOCALSTORE_IID \
+{ 0xdf71c6f1, 0xec53, 0x11d2, { 0xbd, 0xca, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+
+// {DF71C6F0-EC53-11d2-BDCA-000064657374}
+#define NS_LOCALSTORE_CID \
+{ 0xdf71c6f0, 0xec53, 0x11d2, { 0xbd, 0xca, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+
+#define NS_LOCALSTORE_CONTRACTID NS_RDF_DATASOURCE_CONTRACTID_PREFIX "local-store"
+
+class nsILocalStore : public nsISupports
+{
+public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILOCALSTORE_IID)
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsILocalStore, NS_ILOCALSTORE_IID)
+
+extern nsresult
+NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
+
+#endif // nsILocalStore_h__
diff --git a/rdf/datasource/nsIRDFFTP.h b/rdf/datasource/nsIRDFFTP.h
new file mode 100644
index 000000000..8965b4a38
--- /dev/null
+++ b/rdf/datasource/nsIRDFFTP.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#ifndef nsIRDFFTP_h__
+#define nsIRDFFTP_h__
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIRDFNode.h"
+
+
+
+#define NS_IRDFFTPDATAOURCE_IID \
+{ 0x1222e6f0, 0xa5e3, 0x11d2, { 0x8b, 0x7c, 0x00, 0x80, 0x5f, 0x8a, 0x7d, 0xb7 } }
+
+class nsIRDFFTPDataSource : public nsIRDFDataSource
+{
+public:
+};
+
+
+#define NS_IRDFFTPDATASOURCECALLBACK_IID \
+{ 0x204a1a00, 0xa5e4, 0x11d2, { 0x8b, 0x7c, 0x00, 0x80, 0x5f, 0x8a, 0x7d, 0xb8 } }
+
+class nsIRDFFTPDataSourceCallback : public nsIStreamListener
+{
+public:
+};
+
+
+#endif // nsIRDFFTP_h__
diff --git a/rdf/datasource/nsLocalStore.cpp b/rdf/datasource/nsLocalStore.cpp
new file mode 100644
index 000000000..b6218b425
--- /dev/null
+++ b/rdf/datasource/nsLocalStore.cpp
@@ -0,0 +1,481 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set cindent tabstop=4 expandtab shiftwidth=4: */
+/* 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/. */
+
+/*
+
+ Implementation for the local store
+
+ */
+
+#include "nsNetUtil.h"
+#include "nsIFile.h"
+#include "nsIURI.h"
+#include "nsIIOService.h"
+#include "nsIOutputStream.h"
+#include "nsIComponentManager.h"
+#include "nsILocalStore.h"
+#include "nsIRDFDataSource.h"
+#include "nsIRDFRemoteDataSource.h"
+#include "nsIRDFService.h"
+#include "nsIServiceManager.h"
+#include "nsRDFCID.h"
+#include "nsXPIDLString.h"
+#include "plstr.h"
+#include "rdf.h"
+#include "nsCOMPtr.h"
+#include "nsWeakPtr.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+#include "nsWeakReference.h"
+#include "nsCRTGlue.h"
+#include "nsCRT.h"
+#include "nsEnumeratorUtils.h"
+#include "nsCycleCollectionParticipant.h"
+
+////////////////////////////////////////////////////////////////////////
+
+class LocalStoreImpl : public nsILocalStore,
+ public nsIRDFDataSource,
+ public nsIRDFRemoteDataSource,
+ public nsIObserver,
+ public nsSupportsWeakReference
+{
+protected:
+ nsCOMPtr<nsIRDFDataSource> mInner;
+
+ LocalStoreImpl();
+ virtual ~LocalStoreImpl();
+ nsresult Init();
+ nsresult CreateLocalStore(nsIFile* aFile);
+ nsresult LoadData();
+
+ friend nsresult
+ NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
+ nsCOMPtr<nsIRDFService> mRDFService;
+
+public:
+ // nsISupports interface
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(LocalStoreImpl, nsILocalStore)
+
+ // nsILocalStore interface
+
+ // nsIRDFDataSource interface. Most of these are just delegated to
+ // the inner, in-memory datasource.
+ NS_IMETHOD GetURI(char* *aURI) override;
+
+ NS_IMETHOD GetSource(nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget,
+ bool aTruthValue,
+ nsIRDFResource** aSource) override {
+ return mInner->GetSource(aProperty, aTarget, aTruthValue, aSource);
+ }
+
+ NS_IMETHOD GetSources(nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget,
+ bool aTruthValue,
+ nsISimpleEnumerator** aSources) override {
+ return mInner->GetSources(aProperty, aTarget, aTruthValue, aSources);
+ }
+
+ NS_IMETHOD GetTarget(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ bool aTruthValue,
+ nsIRDFNode** aTarget) override {
+ return mInner->GetTarget(aSource, aProperty, aTruthValue, aTarget);
+ }
+
+ NS_IMETHOD GetTargets(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ bool aTruthValue,
+ nsISimpleEnumerator** aTargets) override {
+ return mInner->GetTargets(aSource, aProperty, aTruthValue, aTargets);
+ }
+
+ NS_IMETHOD Assert(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget,
+ bool aTruthValue) override {
+ return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
+ }
+
+ NS_IMETHOD Unassert(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget) override {
+ return mInner->Unassert(aSource, aProperty, aTarget);
+ }
+
+ NS_IMETHOD Change(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aOldTarget,
+ nsIRDFNode* aNewTarget) override {
+ return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
+ }
+
+ NS_IMETHOD Move(nsIRDFResource* aOldSource,
+ nsIRDFResource* aNewSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget) override {
+ return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
+ }
+
+ NS_IMETHOD HasAssertion(nsIRDFResource* aSource,
+ nsIRDFResource* aProperty,
+ nsIRDFNode* aTarget,
+ bool aTruthValue,
+ bool* hasAssertion) override {
+ return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, hasAssertion);
+ }
+
+ NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *_retval) override {
+ return mInner->HasArcIn(aNode, aArc, _retval);
+ }
+
+ NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *_retval) override {
+ return mInner->HasArcOut(aSource, aArc, _retval);
+ }
+
+ NS_IMETHOD ArcLabelsIn(nsIRDFNode* aNode,
+ nsISimpleEnumerator** aLabels) override {
+ return mInner->ArcLabelsIn(aNode, aLabels);
+ }
+
+ NS_IMETHOD ArcLabelsOut(nsIRDFResource* aSource,
+ nsISimpleEnumerator** aLabels) override {
+ return mInner->ArcLabelsOut(aSource, aLabels);
+ }
+
+ NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) override {
+ return mInner->GetAllResources(aResult);
+ }
+
+ NS_IMETHOD GetAllCmds(nsIRDFResource* aSource,
+ nsISimpleEnumerator/*<nsIRDFResource>*/** aCommands) override;
+
+ NS_IMETHOD IsCommandEnabled(nsISupports* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports* aArguments,
+ bool* aResult) override;
+
+ NS_IMETHOD DoCommand(nsISupports* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports* aArguments) override;
+
+ NS_IMETHOD BeginUpdateBatch() override {
+ return mInner->BeginUpdateBatch();
+ }
+
+ NS_IMETHOD EndUpdateBatch() override {
+ return mInner->EndUpdateBatch();
+ }
+
+ NS_IMETHOD GetLoaded(bool* _result) override;
+ NS_IMETHOD Init(const char *uri) override;
+ NS_IMETHOD Flush() override;
+ NS_IMETHOD FlushTo(const char *aURI) override;
+ NS_IMETHOD Refresh(bool sync) override;
+
+ // nsIObserver
+ NS_DECL_NSIOBSERVER
+};
+
+////////////////////////////////////////////////////////////////////////
+
+
+LocalStoreImpl::LocalStoreImpl(void)
+{
+}
+
+LocalStoreImpl::~LocalStoreImpl(void)
+{
+ if (mRDFService)
+ mRDFService->UnregisterDataSource(this);
+}
+
+
+nsresult
+NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult)
+{
+ NS_PRECONDITION(aOuter == nullptr, "no aggregation");
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ NS_PRECONDITION(aResult != nullptr, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ LocalStoreImpl* impl = new LocalStoreImpl();
+ if (! impl)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(impl);
+
+ nsresult rv;
+ rv = impl->Init();
+ if (NS_SUCCEEDED(rv)) {
+ // Set up the result pointer
+ rv = impl->QueryInterface(aIID, aResult);
+ }
+
+ NS_RELEASE(impl);
+ return rv;
+}
+
+NS_IMPL_CYCLE_COLLECTION(LocalStoreImpl, mInner)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(LocalStoreImpl)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(LocalStoreImpl)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStoreImpl)
+ NS_INTERFACE_MAP_ENTRY(nsILocalStore)
+ NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+ NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
+ NS_INTERFACE_MAP_ENTRY(nsIObserver)
+ NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILocalStore)
+NS_INTERFACE_MAP_END
+
+// nsILocalStore interface
+
+// nsIRDFDataSource interface
+
+NS_IMETHODIMP
+LocalStoreImpl::GetLoaded(bool* _result)
+{
+ nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
+ NS_ASSERTION(remote != nullptr, "not an nsIRDFRemoteDataSource");
+ if (! remote)
+ return NS_ERROR_UNEXPECTED;
+
+ return remote->GetLoaded(_result);
+}
+
+
+NS_IMETHODIMP
+LocalStoreImpl::Init(const char *uri)
+{
+ return(NS_OK);
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::Flush()
+{
+ nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
+ // FIXME Bug 340242: Temporarily make this a warning rather than an
+ // assertion until we sort out the ordering of how we write
+ // everything to the localstore, flush it, and disconnect it when
+ // we're getting profile-change notifications.
+ NS_WARNING_ASSERTION(remote != nullptr, "not an nsIRDFRemoteDataSource");
+ if (! remote)
+ return NS_ERROR_UNEXPECTED;
+
+ return remote->Flush();
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::FlushTo(const char *aURI)
+{
+ // Do not ever implement this (security)
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::Refresh(bool sync)
+{
+ nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
+ NS_ASSERTION(remote != nullptr, "not an nsIRDFRemoteDataSource");
+ if (! remote)
+ return NS_ERROR_UNEXPECTED;
+
+ return remote->Refresh(sync);
+}
+
+nsresult
+LocalStoreImpl::Init()
+{
+ nsresult rv;
+
+ rv = LoadData();
+ if (NS_FAILED(rv)) return rv;
+
+ // register this as a named data source with the RDF service
+ mRDFService = do_GetService(NS_RDF_CONTRACTID "/rdf-service;1", &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ mRDFService->RegisterDataSource(this, false);
+
+ // Register as an observer of profile changes
+ nsCOMPtr<nsIObserverService> obs =
+ do_GetService("@mozilla.org/observer-service;1");
+
+ if (obs) {
+ obs->AddObserver(this, "profile-before-change", true);
+ obs->AddObserver(this, "profile-do-change", true);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+LocalStoreImpl::CreateLocalStore(nsIFile* aFile)
+{
+ nsresult rv;
+
+ rv = aFile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIOutputStream> outStream;
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), aFile);
+ if (NS_FAILED(rv)) return rv;
+
+ const char defaultRDF[] =
+ "<?xml version=\"1.0\"?>\n" \
+ "<RDF:RDF xmlns:RDF=\"" RDF_NAMESPACE_URI "\"\n" \
+ " xmlns:NC=\"" NC_NAMESPACE_URI "\">\n" \
+ " <!-- Empty -->\n" \
+ "</RDF:RDF>\n";
+
+ uint32_t count;
+ rv = outStream->Write(defaultRDF, sizeof(defaultRDF)-1, &count);
+ if (NS_FAILED(rv)) return rv;
+
+ if (count != sizeof(defaultRDF)-1)
+ return NS_ERROR_UNEXPECTED;
+
+ // Okay, now see if the file exists _for real_. If it's still
+ // not there, it could be that the profile service gave us
+ // back a read-only directory. Whatever.
+ bool fileExistsFlag = false;
+ aFile->Exists(&fileExistsFlag);
+ if (!fileExistsFlag)
+ return NS_ERROR_UNEXPECTED;
+
+ return NS_OK;
+}
+
+nsresult
+LocalStoreImpl::LoadData()
+{
+ nsresult rv;
+
+ // Look for localstore.rdf in the current profile
+ // directory. Bomb if we can't find it.
+
+ nsCOMPtr<nsIFile> aFile;
+ rv = NS_GetSpecialDirectory(NS_APP_LOCALSTORE_50_FILE, getter_AddRefs(aFile));
+ if (NS_FAILED(rv)) return rv;
+
+ bool fileExistsFlag = false;
+ (void)aFile->Exists(&fileExistsFlag);
+ if (!fileExistsFlag) {
+ // if file doesn't exist, create it
+ rv = CreateLocalStore(aFile);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ mInner = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "xml-datasource", &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIURI> aURI;
+ rv = NS_NewFileURI(getter_AddRefs(aURI), aFile);
+ if (NS_FAILED(rv)) return rv;
+
+ nsAutoCString spec;
+ rv = aURI->GetSpec(spec);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = remote->Init(spec.get());
+ if (NS_FAILED(rv)) return rv;
+
+ // Read the datasource synchronously.
+ rv = remote->Refresh(true);
+
+ if (NS_FAILED(rv)) {
+ // Load failed, delete and recreate a fresh localstore
+ aFile->Remove(true);
+ rv = CreateLocalStore(aFile);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = remote->Refresh(true);
+ }
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+LocalStoreImpl::GetURI(char* *aURI)
+{
+ NS_PRECONDITION(aURI != nullptr, "null ptr");
+ if (! aURI)
+ return NS_ERROR_NULL_POINTER;
+
+ *aURI = NS_strdup("rdf:local-store");
+ if (! *aURI)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+LocalStoreImpl::GetAllCmds(nsIRDFResource* aSource,
+ nsISimpleEnumerator/*<nsIRDFResource>*/** aCommands)
+{
+ return(NS_NewEmptyEnumerator(aCommands));
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::IsCommandEnabled(nsISupports* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports* aArguments,
+ bool* aResult)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::DoCommand(nsISupports* aSources,
+ nsIRDFResource* aCommand,
+ nsISupports* aArguments)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+LocalStoreImpl::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
+{
+ nsresult rv = NS_OK;
+
+ if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
+ // Write out the old datasource's contents.
+ if (mInner) {
+ nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
+ if (remote)
+ remote->Flush();
+ }
+
+ // Create an in-memory datasource for use while we're
+ // profile-less.
+ mInner = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "in-memory-datasource");
+ }
+ else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
+ rv = LoadData();
+ }
+ return rv;
+}
diff --git a/rdf/datasource/nsRDFBuiltInDataSources.h b/rdf/datasource/nsRDFBuiltInDataSources.h
new file mode 100644
index 000000000..297fe7164
--- /dev/null
+++ b/rdf/datasource/nsRDFBuiltInDataSources.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+
+ This header file just contains prototypes for the factory methods
+ for "builtin" data sources that are included in rdf.dll.
+
+ Each of these data sources is exposed to the external world via its
+ CID in ../include/nsRDFCID.h.
+
+ */
+
+#ifndef nsBuiltinDataSources_h__
+#define nsBuiltinDataSources_h__
+
+#include "nsError.h"
+
+class nsIRDFDataSource;
+
+// in nsFileSystemDataSource.cpp
+nsresult NS_NewRDFFileSystemDataSource(nsIRDFDataSource** result);
+
+#endif // nsBuiltinDataSources_h__
+