Bumping manifests a=b2g-bump
[gecko.git] / rdf / datasource / nsFileSystemDataSource.cpp
blob4ccca1d6009dc8c88c599c2c14e766a811477796
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 Implementation for a file system RDF data store.
8 */
10 #include "nsFileSystemDataSource.h"
12 #include <ctype.h> // for toupper()
13 #include <stdio.h>
14 #include "nsArrayEnumerator.h"
15 #include "nsCOMArray.h"
16 #include "nsISupportsArray.h"
17 #include "nsIRDFDataSource.h"
18 #include "nsIRDFObserver.h"
19 #include "nsIServiceManager.h"
20 #include "nsXPIDLString.h"
21 #include "nsRDFCID.h"
22 #include "rdfutil.h"
23 #include "rdf.h"
24 #include "nsEnumeratorUtils.h"
25 #include "nsIURL.h"
26 #include "nsIFileURL.h"
27 #include "nsNetUtil.h"
28 #include "nsIChannel.h"
29 #include "nsIFile.h"
30 #include "nsEscape.h"
31 #include "nsCRTGlue.h"
32 #include "nsAutoPtr.h"
34 #ifdef XP_WIN
35 #include "windef.h"
36 #include "winbase.h"
37 #include "nsILineInputStream.h"
38 #include "nsDirectoryServiceDefs.h"
39 #endif
41 #define NS_MOZICON_SCHEME "moz-icon:"
43 static const char kFileProtocol[] = "file://";
45 bool
46 FileSystemDataSource::isFileURI(nsIRDFResource *r)
48 bool isFileURIFlag = false;
49 const char *uri = nullptr;
51 r->GetValueConst(&uri);
52 if ((uri) && (!strncmp(uri, kFileProtocol, sizeof(kFileProtocol) - 1)))
54 // XXX HACK HACK HACK
55 if (!strchr(uri, '#'))
57 isFileURIFlag = true;
60 return(isFileURIFlag);
65 bool
66 FileSystemDataSource::isDirURI(nsIRDFResource* source)
68 nsresult rv;
69 const char *uri = nullptr;
71 rv = source->GetValueConst(&uri);
72 if (NS_FAILED(rv)) return(false);
74 nsCOMPtr<nsIFile> aDir;
76 rv = NS_GetFileFromURLSpec(nsDependentCString(uri), getter_AddRefs(aDir));
77 if (NS_FAILED(rv)) return(false);
79 bool isDirFlag = false;
81 rv = aDir->IsDirectory(&isDirFlag);
82 if (NS_FAILED(rv)) return(false);
84 return(isDirFlag);
88 nsresult
89 FileSystemDataSource::Init()
91 nsresult rv;
93 mRDFService = do_GetService("@mozilla.org/rdf/rdf-service;1");
94 NS_ENSURE_TRUE(mRDFService, NS_ERROR_FAILURE);
96 rv = mRDFService->GetResource(NS_LITERAL_CSTRING("NC:FilesRoot"),
97 getter_AddRefs(mNC_FileSystemRoot));
98 nsresult tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
99 getter_AddRefs(mNC_Child));
100 if (NS_FAILED(tmp)) {
101 rv = tmp;
103 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
104 getter_AddRefs(mNC_Name));
105 if (NS_FAILED(tmp)) {
106 rv = tmp;
108 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
109 getter_AddRefs(mNC_URL));
110 if (NS_FAILED(tmp)) {
111 rv = tmp;
113 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Icon"),
114 getter_AddRefs(mNC_Icon));
115 if (NS_FAILED(tmp)) {
116 rv = tmp;
118 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"),
119 getter_AddRefs(mNC_Length));
120 if (NS_FAILED(tmp)) {
121 rv = tmp;
123 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsDirectory"),
124 getter_AddRefs(mNC_IsDirectory));
125 if (NS_FAILED(tmp)) {
126 rv = tmp;
128 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
129 getter_AddRefs(mWEB_LastMod));
130 if (NS_FAILED(tmp)) {
131 rv = tmp;
133 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "FileSystemObject"),
134 getter_AddRefs(mNC_FileSystemObject));
135 if (NS_FAILED(tmp)) {
136 rv = tmp;
138 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "pulse"),
139 getter_AddRefs(mNC_pulse));
140 if (NS_FAILED(tmp)) {
141 rv = tmp;
143 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
144 getter_AddRefs(mRDF_InstanceOf));
145 if (NS_FAILED(tmp)) {
146 rv = tmp;
148 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
149 getter_AddRefs(mRDF_type));
151 static const char16_t kTrue[] = {'t','r','u','e','\0'};
152 static const char16_t kFalse[] = {'f','a','l','s','e','\0'};
154 tmp = mRDFService->GetLiteral(kTrue, getter_AddRefs(mLiteralTrue));
155 if (NS_FAILED(tmp)) {
156 rv = tmp;
158 tmp = mRDFService->GetLiteral(kFalse, getter_AddRefs(mLiteralFalse));
159 if (NS_FAILED(tmp)) {
160 rv = tmp;
162 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
164 #ifdef USE_NC_EXTENSION
165 rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "extension"),
166 getter_AddRefs(mNC_extension));
167 NS_ENSURE_SUCCESS(rv, rv);
168 #endif
170 #ifdef XP_WIN
171 rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavorite"),
172 getter_AddRefs(mNC_IEFavoriteObject));
173 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavoriteFolder"),
174 getter_AddRefs(mNC_IEFavoriteFolder));
175 if (NS_FAILED(tmp)) {
176 rv = tmp;
178 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
180 nsCOMPtr<nsIFile> file;
181 NS_GetSpecialDirectory(NS_WIN_FAVORITES_DIR, getter_AddRefs(file));
182 if (file)
184 nsCOMPtr<nsIURI> furi;
185 NS_NewFileURI(getter_AddRefs(furi), file);
186 NS_ENSURE_TRUE(furi, NS_ERROR_FAILURE);
188 file->GetNativePath(ieFavoritesDir);
190 #endif
192 return NS_OK;
195 //static
196 nsresult
197 FileSystemDataSource::Create(nsISupports* aOuter, const nsIID& aIID, void **aResult)
199 NS_ENSURE_NO_AGGREGATION(aOuter);
201 nsRefPtr<FileSystemDataSource> self = new FileSystemDataSource();
202 if (!self)
203 return NS_ERROR_OUT_OF_MEMORY;
205 nsresult rv = self->Init();
206 NS_ENSURE_SUCCESS(rv, rv);
208 return self->QueryInterface(aIID, aResult);
211 NS_IMPL_ISUPPORTS(FileSystemDataSource, nsIRDFDataSource)
213 NS_IMETHODIMP
214 FileSystemDataSource::GetURI(char **uri)
216 NS_PRECONDITION(uri != nullptr, "null ptr");
217 if (! uri)
218 return NS_ERROR_NULL_POINTER;
220 if ((*uri = NS_strdup("rdf:files")) == nullptr)
221 return NS_ERROR_OUT_OF_MEMORY;
223 return NS_OK;
228 NS_IMETHODIMP
229 FileSystemDataSource::GetSource(nsIRDFResource* property,
230 nsIRDFNode* target,
231 bool tv,
232 nsIRDFResource** source /* out */)
234 NS_PRECONDITION(property != nullptr, "null ptr");
235 if (! property)
236 return NS_ERROR_NULL_POINTER;
238 NS_PRECONDITION(target != nullptr, "null ptr");
239 if (! target)
240 return NS_ERROR_NULL_POINTER;
242 NS_PRECONDITION(source != nullptr, "null ptr");
243 if (! source)
244 return NS_ERROR_NULL_POINTER;
246 *source = nullptr;
247 return NS_RDF_NO_VALUE;
252 NS_IMETHODIMP
253 FileSystemDataSource::GetSources(nsIRDFResource *property,
254 nsIRDFNode *target,
255 bool tv,
256 nsISimpleEnumerator **sources /* out */)
258 // NS_NOTYETIMPLEMENTED("write me");
259 return NS_ERROR_NOT_IMPLEMENTED;
264 NS_IMETHODIMP
265 FileSystemDataSource::GetTarget(nsIRDFResource *source,
266 nsIRDFResource *property,
267 bool tv,
268 nsIRDFNode **target /* out */)
270 NS_PRECONDITION(source != nullptr, "null ptr");
271 if (! source)
272 return NS_ERROR_NULL_POINTER;
274 NS_PRECONDITION(property != nullptr, "null ptr");
275 if (! property)
276 return NS_ERROR_NULL_POINTER;
278 NS_PRECONDITION(target != nullptr, "null ptr");
279 if (! target)
280 return NS_ERROR_NULL_POINTER;
282 *target = nullptr;
284 nsresult rv = NS_RDF_NO_VALUE;
286 // we only have positive assertions in the file system data source.
287 if (! tv)
288 return NS_RDF_NO_VALUE;
290 if (source == mNC_FileSystemRoot)
292 if (property == mNC_pulse)
294 nsIRDFLiteral *pulseLiteral;
295 mRDFService->GetLiteral(MOZ_UTF16("12"), &pulseLiteral);
296 *target = pulseLiteral;
297 return NS_OK;
300 else if (isFileURI(source))
302 if (property == mNC_Name)
304 nsCOMPtr<nsIRDFLiteral> name;
305 rv = GetName(source, getter_AddRefs(name));
306 if (NS_FAILED(rv)) return(rv);
307 if (!name) rv = NS_RDF_NO_VALUE;
308 if (rv == NS_RDF_NO_VALUE) return(rv);
309 return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
311 else if (property == mNC_URL)
313 nsCOMPtr<nsIRDFLiteral> url;
314 rv = GetURL(source, nullptr, getter_AddRefs(url));
315 if (NS_FAILED(rv)) return(rv);
316 if (!url) rv = NS_RDF_NO_VALUE;
317 if (rv == NS_RDF_NO_VALUE) return(rv);
319 return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
321 else if (property == mNC_Icon)
323 nsCOMPtr<nsIRDFLiteral> url;
324 bool isFavorite = false;
325 rv = GetURL(source, &isFavorite, getter_AddRefs(url));
326 if (NS_FAILED(rv)) return(rv);
327 if (isFavorite || !url) rv = NS_RDF_NO_VALUE;
328 if (rv == NS_RDF_NO_VALUE) return(rv);
330 const char16_t *uni = nullptr;
331 url->GetValueConst(&uni);
332 if (!uni) return(NS_RDF_NO_VALUE);
333 nsAutoString urlStr;
334 urlStr.Assign(NS_LITERAL_STRING(NS_MOZICON_SCHEME).get());
335 urlStr.Append(uni);
337 rv = mRDFService->GetLiteral(urlStr.get(), getter_AddRefs(url));
338 if (NS_FAILED(rv) || !url) return(NS_RDF_NO_VALUE);
339 return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
341 else if (property == mNC_Length)
343 nsCOMPtr<nsIRDFInt> fileSize;
344 rv = GetFileSize(source, getter_AddRefs(fileSize));
345 if (NS_FAILED(rv)) return(rv);
346 if (!fileSize) rv = NS_RDF_NO_VALUE;
347 if (rv == NS_RDF_NO_VALUE) return(rv);
349 return fileSize->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
351 else if (property == mNC_IsDirectory)
353 *target = (isDirURI(source)) ? mLiteralTrue : mLiteralFalse;
354 NS_ADDREF(*target);
355 return NS_OK;
357 else if (property == mWEB_LastMod)
359 nsCOMPtr<nsIRDFDate> lastMod;
360 rv = GetLastMod(source, getter_AddRefs(lastMod));
361 if (NS_FAILED(rv)) return(rv);
362 if (!lastMod) rv = NS_RDF_NO_VALUE;
363 if (rv == NS_RDF_NO_VALUE) return(rv);
365 return lastMod->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
367 else if (property == mRDF_type)
369 nsCString type;
370 rv = mNC_FileSystemObject->GetValueUTF8(type);
371 if (NS_FAILED(rv)) return(rv);
373 #ifdef XP_WIN
374 // under Windows, if its an IE favorite, return that type
375 if (!ieFavoritesDir.IsEmpty())
377 nsCString uri;
378 rv = source->GetValueUTF8(uri);
379 if (NS_FAILED(rv)) return(rv);
381 NS_ConvertUTF8toUTF16 theURI(uri);
383 if (theURI.Find(ieFavoritesDir) == 0)
385 if (theURI[theURI.Length() - 1] == '/')
387 rv = mNC_IEFavoriteFolder->GetValueUTF8(type);
389 else
391 rv = mNC_IEFavoriteObject->GetValueUTF8(type);
393 if (NS_FAILED(rv)) return(rv);
396 #endif
398 NS_ConvertUTF8toUTF16 url(type);
399 nsCOMPtr<nsIRDFLiteral> literal;
400 mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
401 rv = literal->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
402 return(rv);
404 else if (property == mNC_pulse)
406 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
407 mRDFService->GetLiteral(MOZ_UTF16("12"), getter_AddRefs(pulseLiteral));
408 rv = pulseLiteral->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
409 return(rv);
411 else if (property == mNC_Child)
413 // Oh this is evil. Somebody kill me now.
414 nsCOMPtr<nsISimpleEnumerator> children;
415 rv = GetFolderList(source, false, true, getter_AddRefs(children));
416 if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE)) return(rv);
418 bool hasMore;
419 rv = children->HasMoreElements(&hasMore);
420 if (NS_FAILED(rv)) return(rv);
422 if (hasMore)
424 nsCOMPtr<nsISupports> isupports;
425 rv = children->GetNext(getter_AddRefs(isupports));
426 if (NS_FAILED(rv)) return(rv);
428 return isupports->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
431 #ifdef USE_NC_EXTENSION
432 else if (property == mNC_extension)
434 nsCOMPtr<nsIRDFLiteral> extension;
435 rv = GetExtension(source, getter_AddRefs(extension));
436 if (!extension) rv = NS_RDF_NO_VALUE;
437 if (rv == NS_RDF_NO_VALUE) return(rv);
438 return extension->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
440 #endif
443 return(NS_RDF_NO_VALUE);
448 NS_IMETHODIMP
449 FileSystemDataSource::GetTargets(nsIRDFResource *source,
450 nsIRDFResource *property,
451 bool tv,
452 nsISimpleEnumerator **targets /* out */)
454 NS_PRECONDITION(source != nullptr, "null ptr");
455 if (! source)
456 return NS_ERROR_NULL_POINTER;
458 NS_PRECONDITION(property != nullptr, "null ptr");
459 if (! property)
460 return NS_ERROR_NULL_POINTER;
462 NS_PRECONDITION(targets != nullptr, "null ptr");
463 if (! targets)
464 return NS_ERROR_NULL_POINTER;
466 *targets = nullptr;
468 // we only have positive assertions in the file system data source.
469 if (! tv)
470 return NS_RDF_NO_VALUE;
472 nsresult rv;
474 if (source == mNC_FileSystemRoot)
476 if (property == mNC_Child)
478 return GetVolumeList(targets);
480 else if (property == mNC_pulse)
482 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
483 mRDFService->GetLiteral(MOZ_UTF16("12"),
484 getter_AddRefs(pulseLiteral));
485 return NS_NewSingletonEnumerator(targets, pulseLiteral);
488 else if (isFileURI(source))
490 if (property == mNC_Child)
492 return GetFolderList(source, false, false, targets);
494 else if (property == mNC_Name)
496 nsCOMPtr<nsIRDFLiteral> name;
497 rv = GetName(source, getter_AddRefs(name));
498 if (NS_FAILED(rv)) return rv;
500 return NS_NewSingletonEnumerator(targets, name);
502 else if (property == mNC_URL)
504 nsCOMPtr<nsIRDFLiteral> url;
505 rv = GetURL(source, nullptr, getter_AddRefs(url));
506 if (NS_FAILED(rv)) return rv;
508 return NS_NewSingletonEnumerator(targets, url);
510 else if (property == mRDF_type)
512 nsCString uri;
513 rv = mNC_FileSystemObject->GetValueUTF8(uri);
514 if (NS_FAILED(rv)) return rv;
516 NS_ConvertUTF8toUTF16 url(uri);
518 nsCOMPtr<nsIRDFLiteral> literal;
519 rv = mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
520 if (NS_FAILED(rv)) return rv;
522 return NS_NewSingletonEnumerator(targets, literal);
524 else if (property == mNC_pulse)
526 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
527 rv = mRDFService->GetLiteral(MOZ_UTF16("12"),
528 getter_AddRefs(pulseLiteral));
529 if (NS_FAILED(rv)) return rv;
531 return NS_NewSingletonEnumerator(targets, pulseLiteral);
535 return NS_NewEmptyEnumerator(targets);
540 NS_IMETHODIMP
541 FileSystemDataSource::Assert(nsIRDFResource *source,
542 nsIRDFResource *property,
543 nsIRDFNode *target,
544 bool tv)
546 return NS_RDF_ASSERTION_REJECTED;
551 NS_IMETHODIMP
552 FileSystemDataSource::Unassert(nsIRDFResource *source,
553 nsIRDFResource *property,
554 nsIRDFNode *target)
556 return NS_RDF_ASSERTION_REJECTED;
561 NS_IMETHODIMP
562 FileSystemDataSource::Change(nsIRDFResource* aSource,
563 nsIRDFResource* aProperty,
564 nsIRDFNode* aOldTarget,
565 nsIRDFNode* aNewTarget)
567 return NS_RDF_ASSERTION_REJECTED;
572 NS_IMETHODIMP
573 FileSystemDataSource::Move(nsIRDFResource* aOldSource,
574 nsIRDFResource* aNewSource,
575 nsIRDFResource* aProperty,
576 nsIRDFNode* aTarget)
578 return NS_RDF_ASSERTION_REJECTED;
583 NS_IMETHODIMP
584 FileSystemDataSource::HasAssertion(nsIRDFResource *source,
585 nsIRDFResource *property,
586 nsIRDFNode *target,
587 bool tv,
588 bool *hasAssertion /* out */)
590 NS_PRECONDITION(source != nullptr, "null ptr");
591 if (! source)
592 return NS_ERROR_NULL_POINTER;
594 NS_PRECONDITION(property != nullptr, "null ptr");
595 if (! property)
596 return NS_ERROR_NULL_POINTER;
598 NS_PRECONDITION(target != nullptr, "null ptr");
599 if (! target)
600 return NS_ERROR_NULL_POINTER;
602 NS_PRECONDITION(hasAssertion != nullptr, "null ptr");
603 if (! hasAssertion)
604 return NS_ERROR_NULL_POINTER;
606 // we only have positive assertions in the file system data source.
607 *hasAssertion = false;
609 if (! tv) {
610 return NS_OK;
613 if ((source == mNC_FileSystemRoot) || isFileURI(source))
615 if (property == mRDF_type)
617 nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(target) );
618 if (resource.get() == mRDF_type)
620 *hasAssertion = true;
623 #ifdef USE_NC_EXTENSION
624 else if (property == mNC_extension)
626 // Cheat just a little here by making dirs always match
627 if (isDirURI(source))
629 *hasAssertion = true;
631 else
633 nsCOMPtr<nsIRDFLiteral> extension;
634 GetExtension(source, getter_AddRefs(extension));
635 if (extension.get() == target)
637 *hasAssertion = true;
641 #endif
642 else if (property == mNC_IsDirectory)
644 bool isDir = isDirURI(source);
645 bool isEqual = false;
646 target->EqualsNode(mLiteralTrue, &isEqual);
647 if (isEqual)
649 *hasAssertion = isDir;
651 else
653 target->EqualsNode(mLiteralFalse, &isEqual);
654 if (isEqual)
655 *hasAssertion = !isDir;
660 return NS_OK;
665 NS_IMETHODIMP
666 FileSystemDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
668 return NS_ERROR_NOT_IMPLEMENTED;
673 NS_IMETHODIMP
674 FileSystemDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
676 *result = false;
678 if (aSource == mNC_FileSystemRoot)
680 *result = (aArc == mNC_Child || aArc == mNC_pulse);
682 else if (isFileURI(aSource))
684 if (aArc == mNC_pulse)
686 *result = true;
688 else if (isDirURI(aSource))
690 #ifdef XP_WIN
691 *result = isValidFolder(aSource);
692 #else
693 *result = true;
694 #endif
696 else if (aArc == mNC_pulse || aArc == mNC_Name || aArc == mNC_Icon ||
697 aArc == mNC_URL || aArc == mNC_Length || aArc == mWEB_LastMod ||
698 aArc == mNC_FileSystemObject || aArc == mRDF_InstanceOf ||
699 aArc == mRDF_type)
701 *result = true;
704 return NS_OK;
709 NS_IMETHODIMP
710 FileSystemDataSource::ArcLabelsIn(nsIRDFNode *node,
711 nsISimpleEnumerator ** labels /* out */)
713 // NS_NOTYETIMPLEMENTED("write me");
714 return NS_ERROR_NOT_IMPLEMENTED;
719 NS_IMETHODIMP
720 FileSystemDataSource::ArcLabelsOut(nsIRDFResource *source,
721 nsISimpleEnumerator **labels /* out */)
723 NS_PRECONDITION(source != nullptr, "null ptr");
724 if (! source)
725 return NS_ERROR_NULL_POINTER;
727 NS_PRECONDITION(labels != nullptr, "null ptr");
728 if (! labels)
729 return NS_ERROR_NULL_POINTER;
731 if (source == mNC_FileSystemRoot)
733 nsCOMArray<nsIRDFResource> resources;
734 resources.SetCapacity(2);
736 resources.AppendObject(mNC_Child);
737 resources.AppendObject(mNC_pulse);
739 return NS_NewArrayEnumerator(labels, resources);
741 else if (isFileURI(source))
743 nsCOMArray<nsIRDFResource> resources;
744 resources.SetCapacity(2);
746 if (isDirURI(source))
748 #ifdef XP_WIN
749 if (isValidFolder(source))
751 resources.AppendObject(mNC_Child);
753 #else
754 resources.AppendObject(mNC_Child);
755 #endif
756 resources.AppendObject(mNC_pulse);
759 return NS_NewArrayEnumerator(labels, resources);
762 return NS_NewEmptyEnumerator(labels);
767 NS_IMETHODIMP
768 FileSystemDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
770 NS_NOTYETIMPLEMENTED("sorry!");
771 return NS_ERROR_NOT_IMPLEMENTED;
776 NS_IMETHODIMP
777 FileSystemDataSource::AddObserver(nsIRDFObserver *n)
779 return NS_ERROR_NOT_IMPLEMENTED;
784 NS_IMETHODIMP
785 FileSystemDataSource::RemoveObserver(nsIRDFObserver *n)
787 return NS_ERROR_NOT_IMPLEMENTED;
792 NS_IMETHODIMP
793 FileSystemDataSource::GetAllCmds(nsIRDFResource* source,
794 nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
796 return(NS_NewEmptyEnumerator(commands));
801 NS_IMETHODIMP
802 FileSystemDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
803 nsIRDFResource* aCommand,
804 nsISupportsArray/*<nsIRDFResource>*/* aArguments,
805 bool* aResult)
807 return(NS_ERROR_NOT_IMPLEMENTED);
812 NS_IMETHODIMP
813 FileSystemDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
814 nsIRDFResource* aCommand,
815 nsISupportsArray/*<nsIRDFResource>*/* aArguments)
817 return(NS_ERROR_NOT_IMPLEMENTED);
822 NS_IMETHODIMP
823 FileSystemDataSource::BeginUpdateBatch()
825 return NS_OK;
830 NS_IMETHODIMP
831 FileSystemDataSource::EndUpdateBatch()
833 return NS_OK;
838 nsresult
839 FileSystemDataSource::GetVolumeList(nsISimpleEnumerator** aResult)
841 nsCOMArray<nsIRDFResource> volumes;
842 nsCOMPtr<nsIRDFResource> vol;
844 #ifdef XP_WIN
846 int32_t driveType;
847 wchar_t drive[32];
848 int32_t volNum;
850 for (volNum = 0; volNum < 26; volNum++)
852 swprintf( drive, L"%c:\\", volNum + (char16_t)'A');
854 driveType = GetDriveTypeW(drive);
855 if (driveType != DRIVE_UNKNOWN && driveType != DRIVE_NO_ROOT_DIR)
857 nsAutoCString url;
858 url.AppendPrintf("file:///%c|/", volNum + 'A');
859 nsresult rv = mRDFService->GetResource(url, getter_AddRefs(vol));
860 if (NS_FAILED(rv))
861 return rv;
863 volumes.AppendObject(vol);
866 #endif
868 #ifdef XP_UNIX
869 mRDFService->GetResource(NS_LITERAL_CSTRING("file:///"), getter_AddRefs(vol));
870 volumes.AppendObject(vol);
871 #endif
873 return NS_NewArrayEnumerator(aResult, volumes);
878 #ifdef XP_WIN
879 bool
880 FileSystemDataSource::isValidFolder(nsIRDFResource *source)
882 bool isValid = true;
883 if (ieFavoritesDir.IsEmpty()) return(isValid);
885 nsresult rv;
886 nsCString uri;
887 rv = source->GetValueUTF8(uri);
888 if (NS_FAILED(rv)) return(isValid);
890 NS_ConvertUTF8toUTF16 theURI(uri);
891 if (theURI.Find(ieFavoritesDir) == 0)
893 isValid = false;
895 nsCOMPtr<nsISimpleEnumerator> folderEnum;
896 if (NS_SUCCEEDED(rv = GetFolderList(source, true, false, getter_AddRefs(folderEnum))))
898 bool hasAny = false, hasMore;
899 while (NS_SUCCEEDED(folderEnum->HasMoreElements(&hasMore)) &&
900 hasMore)
902 hasAny = true;
904 nsCOMPtr<nsISupports> isupports;
905 if (NS_FAILED(rv = folderEnum->GetNext(getter_AddRefs(isupports))))
906 break;
907 nsCOMPtr<nsIRDFResource> res = do_QueryInterface(isupports);
908 if (!res) break;
910 nsCOMPtr<nsIRDFLiteral> nameLiteral;
911 if (NS_FAILED(rv = GetName(res, getter_AddRefs(nameLiteral))))
912 break;
914 const char16_t *uniName;
915 if (NS_FAILED(rv = nameLiteral->GetValueConst(&uniName)))
916 break;
917 nsAutoString name(uniName);
919 // An empty folder, or a folder that contains just "desktop.ini",
920 // is considered to be a IE Favorite; otherwise, its a folder
921 if (!name.LowerCaseEqualsLiteral("desktop.ini"))
923 isValid = true;
924 break;
927 if (!hasAny) isValid = true;
930 return(isValid);
932 #endif
936 nsresult
937 FileSystemDataSource::GetFolderList(nsIRDFResource *source, bool allowHidden,
938 bool onlyFirst, nsISimpleEnumerator** aResult)
940 if (!isDirURI(source))
941 return(NS_RDF_NO_VALUE);
943 nsresult rv;
945 const char *parentURI = nullptr;
946 rv = source->GetValueConst(&parentURI);
947 if (NS_FAILED(rv))
948 return(rv);
949 if (!parentURI)
950 return(NS_ERROR_UNEXPECTED);
952 nsCOMPtr<nsIURI> aIURI;
953 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(parentURI))))
954 return(rv);
956 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
957 if (!fileURL)
958 return NS_OK;
960 nsCOMPtr<nsIFile> aDir;
961 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aDir))))
962 return(rv);
964 // ensure that we DO NOT resolve aliases
965 aDir->SetFollowLinks(false);
967 nsCOMPtr<nsISimpleEnumerator> dirContents;
968 if (NS_FAILED(rv = aDir->GetDirectoryEntries(getter_AddRefs(dirContents))))
969 return(rv);
970 if (!dirContents)
971 return(NS_ERROR_UNEXPECTED);
973 nsCOMArray<nsIRDFResource> resources;
974 bool hasMore;
975 while(NS_SUCCEEDED(rv = dirContents->HasMoreElements(&hasMore)) &&
976 hasMore)
978 nsCOMPtr<nsISupports> isupports;
979 if (NS_FAILED(rv = dirContents->GetNext(getter_AddRefs(isupports))))
980 break;
982 nsCOMPtr<nsIFile> aFile = do_QueryInterface(isupports);
983 if (!aFile)
984 break;
986 if (!allowHidden)
988 bool hiddenFlag = false;
989 if (NS_FAILED(rv = aFile->IsHidden(&hiddenFlag)))
990 break;
991 if (hiddenFlag)
992 continue;
995 nsAutoString leafStr;
996 if (NS_FAILED(rv = aFile->GetLeafName(leafStr)))
997 break;
998 if (leafStr.IsEmpty())
999 continue;
1001 nsAutoCString fullURI;
1002 fullURI.Assign(parentURI);
1003 if (fullURI.Last() != '/')
1005 fullURI.Append('/');
1008 char *escLeafStr = nsEscape(NS_ConvertUTF16toUTF8(leafStr).get(), url_Path);
1009 leafStr.Truncate();
1011 if (!escLeafStr)
1012 continue;
1014 nsAutoCString leaf(escLeafStr);
1015 NS_Free(escLeafStr);
1016 escLeafStr = nullptr;
1018 // using nsEscape() [above] doesn't escape slashes, so do that by hand
1019 int32_t aOffset;
1020 while ((aOffset = leaf.FindChar('/')) >= 0)
1022 leaf.Cut((uint32_t)aOffset, 1);
1023 leaf.Insert("%2F", (uint32_t)aOffset);
1026 // append the encoded name
1027 fullURI.Append(leaf);
1029 bool dirFlag = false;
1030 rv = aFile->IsDirectory(&dirFlag);
1031 if (NS_SUCCEEDED(rv) && dirFlag)
1033 fullURI.Append('/');
1036 nsCOMPtr<nsIRDFResource> fileRes;
1037 mRDFService->GetResource(fullURI, getter_AddRefs(fileRes));
1039 resources.AppendObject(fileRes);
1041 if (onlyFirst)
1042 break;
1045 return NS_NewArrayEnumerator(aResult, resources);
1048 nsresult
1049 FileSystemDataSource::GetLastMod(nsIRDFResource *source, nsIRDFDate **aResult)
1051 *aResult = nullptr;
1053 nsresult rv;
1054 const char *uri = nullptr;
1056 rv = source->GetValueConst(&uri);
1057 if (NS_FAILED(rv)) return(rv);
1058 if (!uri)
1059 return(NS_ERROR_UNEXPECTED);
1061 nsCOMPtr<nsIURI> aIURI;
1062 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1063 return(rv);
1065 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1066 if (!fileURL)
1067 return NS_OK;
1069 nsCOMPtr<nsIFile> aFile;
1070 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1071 return(rv);
1072 if (!aFile)
1073 return(NS_ERROR_UNEXPECTED);
1075 // ensure that we DO NOT resolve aliases
1076 aFile->SetFollowLinks(false);
1078 PRTime lastModDate;
1079 if (NS_FAILED(rv = aFile->GetLastModifiedTime(&lastModDate)))
1080 return(rv);
1082 // convert from milliseconds to seconds
1083 mRDFService->GetDateLiteral(lastModDate * PR_MSEC_PER_SEC, aResult);
1085 return(NS_OK);
1090 nsresult
1091 FileSystemDataSource::GetFileSize(nsIRDFResource *source, nsIRDFInt **aResult)
1093 *aResult = nullptr;
1095 nsresult rv;
1096 const char *uri = nullptr;
1098 rv = source->GetValueConst(&uri);
1099 if (NS_FAILED(rv))
1100 return(rv);
1101 if (!uri)
1102 return(NS_ERROR_UNEXPECTED);
1104 nsCOMPtr<nsIURI> aIURI;
1105 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1106 return(rv);
1108 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1109 if (!fileURL)
1110 return NS_OK;
1112 nsCOMPtr<nsIFile> aFile;
1113 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1114 return(rv);
1115 if (!aFile)
1116 return(NS_ERROR_UNEXPECTED);
1118 // ensure that we DO NOT resolve aliases
1119 aFile->SetFollowLinks(false);
1121 // don't do anything with directories
1122 bool isDir = false;
1123 if (NS_FAILED(rv = aFile->IsDirectory(&isDir)))
1124 return(rv);
1125 if (isDir)
1126 return(NS_RDF_NO_VALUE);
1128 int64_t aFileSize64;
1129 if (NS_FAILED(rv = aFile->GetFileSize(&aFileSize64)))
1130 return(rv);
1132 // convert 64bits to 32bits
1133 int32_t aFileSize32 = int32_t(aFileSize64);
1134 mRDFService->GetIntLiteral(aFileSize32, aResult);
1136 return(NS_OK);
1141 nsresult
1142 FileSystemDataSource::GetName(nsIRDFResource *source, nsIRDFLiteral **aResult)
1144 nsresult rv;
1145 const char *uri = nullptr;
1147 rv = source->GetValueConst(&uri);
1148 if (NS_FAILED(rv))
1149 return(rv);
1150 if (!uri)
1151 return(NS_ERROR_UNEXPECTED);
1153 nsCOMPtr<nsIURI> aIURI;
1154 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1155 return(rv);
1157 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1158 if (!fileURL)
1159 return NS_OK;
1161 nsCOMPtr<nsIFile> aFile;
1162 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1163 return(rv);
1164 if (!aFile)
1165 return(NS_ERROR_UNEXPECTED);
1167 // ensure that we DO NOT resolve aliases
1168 aFile->SetFollowLinks(false);
1170 nsAutoString name;
1171 if (NS_FAILED(rv = aFile->GetLeafName(name)))
1172 return(rv);
1173 if (name.IsEmpty())
1174 return(NS_ERROR_UNEXPECTED);
1176 #ifdef XP_WIN
1177 // special hack for IE favorites under Windows; strip off the
1178 // trailing ".url" or ".lnk" at the end of IE favorites names
1179 int32_t nameLen = name.Length();
1180 if ((strncmp(uri, ieFavoritesDir.get(), ieFavoritesDir.Length()) == 0) && (nameLen > 4))
1182 nsAutoString extension;
1183 name.Right(extension, 4);
1184 if (extension.LowerCaseEqualsLiteral(".url") ||
1185 extension.LowerCaseEqualsLiteral(".lnk"))
1187 name.Truncate(nameLen - 4);
1190 #endif
1192 mRDFService->GetLiteral(name.get(), aResult);
1194 return NS_OK;
1199 #ifdef USE_NC_EXTENSION
1200 nsresult
1201 FileSystemDataSource::GetExtension(nsIRDFResource *source, nsIRDFLiteral **aResult)
1203 nsCOMPtr<nsIRDFLiteral> name;
1204 nsresult rv = GetName(source, getter_AddRefs(name));
1205 if (NS_FAILED(rv))
1206 return rv;
1208 const char16_t* unicodeLeafName;
1209 rv = name->GetValueConst(&unicodeLeafName);
1210 if (NS_FAILED(rv))
1211 return rv;
1213 nsAutoString filename(unicodeLeafName);
1214 int32_t lastDot = filename.RFindChar('.');
1215 if (lastDot == -1)
1217 mRDFService->GetLiteral(EmptyString().get(), aResult);
1219 else
1221 nsAutoString extension;
1222 filename.Right(extension, (filename.Length() - lastDot));
1223 mRDFService->GetLiteral(extension.get(), aResult);
1226 return NS_OK;
1228 #endif
1230 #ifdef XP_WIN
1231 nsresult
1232 FileSystemDataSource::getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral)
1234 nsresult rv = NS_OK;
1236 *urlLiteral = nullptr;
1238 nsCOMPtr<nsIFile> f;
1239 NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileURL), getter_AddRefs(f));
1241 bool value;
1243 if (NS_SUCCEEDED(f->IsDirectory(&value)) && value)
1245 if (isValidFolder(source))
1246 return(NS_RDF_NO_VALUE);
1247 aFileURL.AppendLiteral("desktop.ini");
1249 else if (aFileURL.Length() > 4)
1251 nsAutoString extension;
1253 aFileURL.Right(extension, 4);
1254 if (!extension.LowerCaseEqualsLiteral(".url"))
1256 return(NS_RDF_NO_VALUE);
1260 nsCOMPtr<nsIInputStream> strm;
1261 NS_NewLocalFileInputStream(getter_AddRefs(strm),f);
1262 nsCOMPtr<nsILineInputStream> linereader = do_QueryInterface(strm, &rv);
1264 nsAutoString line;
1265 nsAutoCString cLine;
1266 while(NS_SUCCEEDED(rv))
1268 bool isEOF;
1269 rv = linereader->ReadLine(cLine, &isEOF);
1270 CopyASCIItoUTF16(cLine, line);
1272 if (isEOF)
1274 if (line.Find("URL=", true) == 0)
1276 line.Cut(0, 4);
1277 rv = mRDFService->GetLiteral(line.get(), urlLiteral);
1278 break;
1280 else if (line.Find("CDFURL=", true) == 0)
1282 line.Cut(0, 7);
1283 rv = mRDFService->GetLiteral(line.get(), urlLiteral);
1284 break;
1286 line.Truncate();
1290 return(rv);
1292 #endif
1296 nsresult
1297 FileSystemDataSource::GetURL(nsIRDFResource *source, bool *isFavorite, nsIRDFLiteral** aResult)
1299 if (isFavorite) *isFavorite = false;
1301 nsresult rv;
1302 nsCString uri;
1304 rv = source->GetValueUTF8(uri);
1305 if (NS_FAILED(rv))
1306 return(rv);
1308 NS_ConvertUTF8toUTF16 url(uri);
1310 #ifdef XP_WIN
1311 // under Windows, if its an IE favorite, munge the URL
1312 if (!ieFavoritesDir.IsEmpty())
1314 if (url.Find(ieFavoritesDir) == 0)
1316 if (isFavorite) *isFavorite = true;
1317 rv = getIEFavoriteURL(source, url, aResult);
1318 return(rv);
1321 #endif
1323 // if we fall through to here, its not any type of bookmark
1324 // stored in the platform native file system, so just set the URL
1326 mRDFService->GetLiteral(url.get(), aResult);
1328 return(NS_OK);