gecko-dev/rdf/datasource/nsFileSystemDataSource.cpp
Eric Rahm d986dfc66d Bug 1309409 - Part 1: Remove nsISupportsArray usage from nsIRDFDataSource. r=Pike
This converts the usage of nsISupportsArray in nsIRDFDataSource to just
nsISupports. Internally none of the params are used, all external usages in
the addons repo appear to just be passthroughs.

Regardless, any external implementors wanting to pass in an nsISupportsArray
can still do so as it is derived from nsISupports.

Additionally the |IsCommandEnabled| and |DoCommand| stubs are updated to just
return NS_ERROR_NOT_IMPLEMENTED as this functionallity is currently not
supported.

MozReview-Commit-ID: JJSHAQKiLSZ
2016-11-04 11:03:26 -07:00

1329 lines
36 KiB
C++

/* -*- 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);
}