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/. */
5
6 /*
7 Implementation for a file system RDF data store.
8 */
9
10 #include "nsFileSystemDataSource.h"
11
12 #include <ctype.h> // for toupper()
13 #include <stdio.h>
14 #include "nsArrayEnumerator.h"
15 #include "nsCOMArray.h"
16 #include "nsIRDFDataSource.h"
17 #include "nsIRDFObserver.h"
18 #include "nsIServiceManager.h"
19 #include "nsXPIDLString.h"
20 #include "nsRDFCID.h"
21 #include "rdfutil.h"
22 #include "rdf.h"
23 #include "nsEnumeratorUtils.h"
24 #include "nsIURL.h"
25 #include "nsIFileURL.h"
26 #include "nsNetUtil.h"
27 #include "nsIInputStream.h"
28 #include "nsIChannel.h"
29 #include "nsIFile.h"
30 #include "nsEscape.h"
31 #include "nsCRTGlue.h"
32 #include "nsAutoPtr.h"
33 #include "prtime.h"
34
35 #ifdef XP_WIN
36 #include "windef.h"
37 #include "winbase.h"
38 #include "nsILineInputStream.h"
39 #include "nsDirectoryServiceDefs.h"
40 #endif
41
42 #define NS_MOZICON_SCHEME "moz-icon:"
43
44 static const char kFileProtocol[] = "file://";
45
46 bool
isFileURI(nsIRDFResource * r)47 FileSystemDataSource::isFileURI(nsIRDFResource *r)
48 {
49 bool isFileURIFlag = false;
50 const char *uri = nullptr;
51
52 r->GetValueConst(&uri);
53 if ((uri) && (!strncmp(uri, kFileProtocol, sizeof(kFileProtocol) - 1)))
54 {
55 // XXX HACK HACK HACK
56 if (!strchr(uri, '#'))
57 {
58 isFileURIFlag = true;
59 }
60 }
61 return(isFileURIFlag);
62 }
63
64
65
66 bool
isDirURI(nsIRDFResource * source)67 FileSystemDataSource::isDirURI(nsIRDFResource* source)
68 {
69 nsresult rv;
70 const char *uri = nullptr;
71
72 rv = source->GetValueConst(&uri);
73 if (NS_FAILED(rv)) return(false);
74
75 nsCOMPtr<nsIFile> aDir;
76
77 rv = NS_GetFileFromURLSpec(nsDependentCString(uri), getter_AddRefs(aDir));
78 if (NS_FAILED(rv)) return(false);
79
80 bool isDirFlag = false;
81
82 rv = aDir->IsDirectory(&isDirFlag);
83 if (NS_FAILED(rv)) return(false);
84
85 return(isDirFlag);
86 }
87
88
89 nsresult
Init()90 FileSystemDataSource::Init()
91 {
92 nsresult rv;
93
94 mRDFService = do_GetService("@mozilla.org/rdf/rdf-service;1");
95 NS_ENSURE_TRUE(mRDFService, NS_ERROR_FAILURE);
96
97 rv = mRDFService->GetResource(NS_LITERAL_CSTRING("NC:FilesRoot"),
98 getter_AddRefs(mNC_FileSystemRoot));
99 nsresult tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
100 getter_AddRefs(mNC_Child));
101 if (NS_FAILED(tmp)) {
102 rv = tmp;
103 }
104 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
105 getter_AddRefs(mNC_Name));
106 if (NS_FAILED(tmp)) {
107 rv = tmp;
108 }
109 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
110 getter_AddRefs(mNC_URL));
111 if (NS_FAILED(tmp)) {
112 rv = tmp;
113 }
114 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Icon"),
115 getter_AddRefs(mNC_Icon));
116 if (NS_FAILED(tmp)) {
117 rv = tmp;
118 }
119 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"),
120 getter_AddRefs(mNC_Length));
121 if (NS_FAILED(tmp)) {
122 rv = tmp;
123 }
124 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsDirectory"),
125 getter_AddRefs(mNC_IsDirectory));
126 if (NS_FAILED(tmp)) {
127 rv = tmp;
128 }
129 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
130 getter_AddRefs(mWEB_LastMod));
131 if (NS_FAILED(tmp)) {
132 rv = tmp;
133 }
134 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "FileSystemObject"),
135 getter_AddRefs(mNC_FileSystemObject));
136 if (NS_FAILED(tmp)) {
137 rv = tmp;
138 }
139 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "pulse"),
140 getter_AddRefs(mNC_pulse));
141 if (NS_FAILED(tmp)) {
142 rv = tmp;
143 }
144 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
145 getter_AddRefs(mRDF_InstanceOf));
146 if (NS_FAILED(tmp)) {
147 rv = tmp;
148 }
149 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
150 getter_AddRefs(mRDF_type));
151
152 static const char16_t kTrue[] = {'t','r','u','e','\0'};
153 static const char16_t kFalse[] = {'f','a','l','s','e','\0'};
154
155 tmp = mRDFService->GetLiteral(kTrue, getter_AddRefs(mLiteralTrue));
156 if (NS_FAILED(tmp)) {
157 rv = tmp;
158 }
159 tmp = mRDFService->GetLiteral(kFalse, getter_AddRefs(mLiteralFalse));
160 if (NS_FAILED(tmp)) {
161 rv = tmp;
162 }
163 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
164
165 #ifdef USE_NC_EXTENSION
166 rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "extension"),
167 getter_AddRefs(mNC_extension));
168 NS_ENSURE_SUCCESS(rv, rv);
169 #endif
170
171 #ifdef XP_WIN
172 rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavorite"),
173 getter_AddRefs(mNC_IEFavoriteObject));
174 tmp = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavoriteFolder"),
175 getter_AddRefs(mNC_IEFavoriteFolder));
176 if (NS_FAILED(tmp)) {
177 rv = tmp;
178 }
179 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
180
181 nsCOMPtr<nsIFile> file;
182 NS_GetSpecialDirectory(NS_WIN_FAVORITES_DIR, getter_AddRefs(file));
183 if (file)
184 {
185 nsCOMPtr<nsIURI> furi;
186 NS_NewFileURI(getter_AddRefs(furi), file);
187 NS_ENSURE_TRUE(furi, NS_ERROR_FAILURE);
188
189 file->GetNativePath(ieFavoritesDir);
190 }
191 #endif
192
193 return NS_OK;
194 }
195
196 //static
197 nsresult
Create(nsISupports * aOuter,const nsIID & aIID,void ** aResult)198 FileSystemDataSource::Create(nsISupports* aOuter, const nsIID& aIID, void **aResult)
199 {
200 NS_ENSURE_NO_AGGREGATION(aOuter);
201
202 RefPtr<FileSystemDataSource> self = new FileSystemDataSource();
203 if (!self)
204 return NS_ERROR_OUT_OF_MEMORY;
205
206 nsresult rv = self->Init();
207 NS_ENSURE_SUCCESS(rv, rv);
208
209 return self->QueryInterface(aIID, aResult);
210 }
211
NS_IMPL_ISUPPORTS(FileSystemDataSource,nsIRDFDataSource)212 NS_IMPL_ISUPPORTS(FileSystemDataSource, nsIRDFDataSource)
213
214 NS_IMETHODIMP
215 FileSystemDataSource::GetURI(char **uri)
216 {
217 NS_PRECONDITION(uri != nullptr, "null ptr");
218 if (! uri)
219 return NS_ERROR_NULL_POINTER;
220
221 if ((*uri = NS_strdup("rdf:files")) == nullptr)
222 return NS_ERROR_OUT_OF_MEMORY;
223
224 return NS_OK;
225 }
226
227
228
229 NS_IMETHODIMP
GetSource(nsIRDFResource * property,nsIRDFNode * target,bool tv,nsIRDFResource ** source)230 FileSystemDataSource::GetSource(nsIRDFResource* property,
231 nsIRDFNode* target,
232 bool tv,
233 nsIRDFResource** source /* out */)
234 {
235 NS_PRECONDITION(property != nullptr, "null ptr");
236 if (! property)
237 return NS_ERROR_NULL_POINTER;
238
239 NS_PRECONDITION(target != nullptr, "null ptr");
240 if (! target)
241 return NS_ERROR_NULL_POINTER;
242
243 NS_PRECONDITION(source != nullptr, "null ptr");
244 if (! source)
245 return NS_ERROR_NULL_POINTER;
246
247 *source = nullptr;
248 return NS_RDF_NO_VALUE;
249 }
250
251
252
253 NS_IMETHODIMP
GetSources(nsIRDFResource * property,nsIRDFNode * target,bool tv,nsISimpleEnumerator ** sources)254 FileSystemDataSource::GetSources(nsIRDFResource *property,
255 nsIRDFNode *target,
256 bool tv,
257 nsISimpleEnumerator **sources /* out */)
258 {
259 // NS_NOTYETIMPLEMENTED("write me");
260 return NS_ERROR_NOT_IMPLEMENTED;
261 }
262
263
264
265 NS_IMETHODIMP
GetTarget(nsIRDFResource * source,nsIRDFResource * property,bool tv,nsIRDFNode ** target)266 FileSystemDataSource::GetTarget(nsIRDFResource *source,
267 nsIRDFResource *property,
268 bool tv,
269 nsIRDFNode **target /* out */)
270 {
271 NS_PRECONDITION(source != nullptr, "null ptr");
272 if (! source)
273 return NS_ERROR_NULL_POINTER;
274
275 NS_PRECONDITION(property != nullptr, "null ptr");
276 if (! property)
277 return NS_ERROR_NULL_POINTER;
278
279 NS_PRECONDITION(target != nullptr, "null ptr");
280 if (! target)
281 return NS_ERROR_NULL_POINTER;
282
283 *target = nullptr;
284
285 nsresult rv = NS_RDF_NO_VALUE;
286
287 // we only have positive assertions in the file system data source.
288 if (! tv)
289 return NS_RDF_NO_VALUE;
290
291 if (source == mNC_FileSystemRoot)
292 {
293 if (property == mNC_pulse)
294 {
295 nsIRDFLiteral *pulseLiteral;
296 mRDFService->GetLiteral(u"12", &pulseLiteral);
297 *target = pulseLiteral;
298 return NS_OK;
299 }
300 }
301 else if (isFileURI(source))
302 {
303 if (property == mNC_Name)
304 {
305 nsCOMPtr<nsIRDFLiteral> name;
306 rv = GetName(source, getter_AddRefs(name));
307 if (NS_FAILED(rv)) return(rv);
308 if (!name) rv = NS_RDF_NO_VALUE;
309 if (rv == NS_RDF_NO_VALUE) return(rv);
310 return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
311 }
312 else if (property == mNC_URL)
313 {
314 nsCOMPtr<nsIRDFLiteral> url;
315 rv = GetURL(source, nullptr, getter_AddRefs(url));
316 if (NS_FAILED(rv)) return(rv);
317 if (!url) rv = NS_RDF_NO_VALUE;
318 if (rv == NS_RDF_NO_VALUE) return(rv);
319
320 return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
321 }
322 else if (property == mNC_Icon)
323 {
324 nsCOMPtr<nsIRDFLiteral> url;
325 bool isFavorite = false;
326 rv = GetURL(source, &isFavorite, getter_AddRefs(url));
327 if (NS_FAILED(rv)) return(rv);
328 if (isFavorite || !url) rv = NS_RDF_NO_VALUE;
329 if (rv == NS_RDF_NO_VALUE) return(rv);
330
331 const char16_t *uni = nullptr;
332 url->GetValueConst(&uni);
333 if (!uni) return(NS_RDF_NO_VALUE);
334 nsAutoString urlStr;
335 urlStr.AssignLiteral(NS_MOZICON_SCHEME);
336 urlStr.Append(uni);
337
338 rv = mRDFService->GetLiteral(urlStr.get(), getter_AddRefs(url));
339 if (NS_FAILED(rv) || !url) return(NS_RDF_NO_VALUE);
340 return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
341 }
342 else if (property == mNC_Length)
343 {
344 nsCOMPtr<nsIRDFInt> fileSize;
345 rv = GetFileSize(source, getter_AddRefs(fileSize));
346 if (NS_FAILED(rv)) return(rv);
347 if (!fileSize) rv = NS_RDF_NO_VALUE;
348 if (rv == NS_RDF_NO_VALUE) return(rv);
349
350 return fileSize->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
351 }
352 else if (property == mNC_IsDirectory)
353 {
354 *target = (isDirURI(source)) ? mLiteralTrue : mLiteralFalse;
355 NS_ADDREF(*target);
356 return NS_OK;
357 }
358 else if (property == mWEB_LastMod)
359 {
360 nsCOMPtr<nsIRDFDate> lastMod;
361 rv = GetLastMod(source, getter_AddRefs(lastMod));
362 if (NS_FAILED(rv)) return(rv);
363 if (!lastMod) rv = NS_RDF_NO_VALUE;
364 if (rv == NS_RDF_NO_VALUE) return(rv);
365
366 return lastMod->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
367 }
368 else if (property == mRDF_type)
369 {
370 nsCString type;
371 rv = mNC_FileSystemObject->GetValueUTF8(type);
372 if (NS_FAILED(rv)) return(rv);
373
374 #ifdef XP_WIN
375 // under Windows, if its an IE favorite, return that type
376 if (!ieFavoritesDir.IsEmpty())
377 {
378 nsCString uri;
379 rv = source->GetValueUTF8(uri);
380 if (NS_FAILED(rv)) return(rv);
381
382 NS_ConvertUTF8toUTF16 theURI(uri);
383
384 if (theURI.Find(ieFavoritesDir) == 0)
385 {
386 if (theURI[theURI.Length() - 1] == '/')
387 {
388 rv = mNC_IEFavoriteFolder->GetValueUTF8(type);
389 }
390 else
391 {
392 rv = mNC_IEFavoriteObject->GetValueUTF8(type);
393 }
394 if (NS_FAILED(rv)) return(rv);
395 }
396 }
397 #endif
398
399 NS_ConvertUTF8toUTF16 url(type);
400 nsCOMPtr<nsIRDFLiteral> literal;
401 mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
402 rv = literal->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
403 return(rv);
404 }
405 else if (property == mNC_pulse)
406 {
407 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
408 mRDFService->GetLiteral(u"12", getter_AddRefs(pulseLiteral));
409 rv = pulseLiteral->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
410 return(rv);
411 }
412 else if (property == mNC_Child)
413 {
414 // Oh this is evil. Somebody kill me now.
415 nsCOMPtr<nsISimpleEnumerator> children;
416 rv = GetFolderList(source, false, true, getter_AddRefs(children));
417 if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE)) return(rv);
418
419 bool hasMore;
420 rv = children->HasMoreElements(&hasMore);
421 if (NS_FAILED(rv)) return(rv);
422
423 if (hasMore)
424 {
425 nsCOMPtr<nsISupports> isupports;
426 rv = children->GetNext(getter_AddRefs(isupports));
427 if (NS_FAILED(rv)) return(rv);
428
429 return isupports->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
430 }
431 }
432 #ifdef USE_NC_EXTENSION
433 else if (property == mNC_extension)
434 {
435 nsCOMPtr<nsIRDFLiteral> extension;
436 rv = GetExtension(source, getter_AddRefs(extension));
437 if (!extension) rv = NS_RDF_NO_VALUE;
438 if (rv == NS_RDF_NO_VALUE) return(rv);
439 return extension->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
440 }
441 #endif
442 }
443
444 return(NS_RDF_NO_VALUE);
445 }
446
447
448
449 NS_IMETHODIMP
GetTargets(nsIRDFResource * source,nsIRDFResource * property,bool tv,nsISimpleEnumerator ** targets)450 FileSystemDataSource::GetTargets(nsIRDFResource *source,
451 nsIRDFResource *property,
452 bool tv,
453 nsISimpleEnumerator **targets /* out */)
454 {
455 NS_PRECONDITION(source != nullptr, "null ptr");
456 if (! source)
457 return NS_ERROR_NULL_POINTER;
458
459 NS_PRECONDITION(property != nullptr, "null ptr");
460 if (! property)
461 return NS_ERROR_NULL_POINTER;
462
463 NS_PRECONDITION(targets != nullptr, "null ptr");
464 if (! targets)
465 return NS_ERROR_NULL_POINTER;
466
467 *targets = nullptr;
468
469 // we only have positive assertions in the file system data source.
470 if (! tv)
471 return NS_RDF_NO_VALUE;
472
473 nsresult rv;
474
475 if (source == mNC_FileSystemRoot)
476 {
477 if (property == mNC_Child)
478 {
479 return GetVolumeList(targets);
480 }
481 else if (property == mNC_pulse)
482 {
483 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
484 mRDFService->GetLiteral(u"12",
485 getter_AddRefs(pulseLiteral));
486 return NS_NewSingletonEnumerator(targets, pulseLiteral);
487 }
488 }
489 else if (isFileURI(source))
490 {
491 if (property == mNC_Child)
492 {
493 return GetFolderList(source, false, false, targets);
494 }
495 else if (property == mNC_Name)
496 {
497 nsCOMPtr<nsIRDFLiteral> name;
498 rv = GetName(source, getter_AddRefs(name));
499 if (NS_FAILED(rv)) return rv;
500
501 return NS_NewSingletonEnumerator(targets, name);
502 }
503 else if (property == mNC_URL)
504 {
505 nsCOMPtr<nsIRDFLiteral> url;
506 rv = GetURL(source, nullptr, getter_AddRefs(url));
507 if (NS_FAILED(rv)) return rv;
508
509 return NS_NewSingletonEnumerator(targets, url);
510 }
511 else if (property == mRDF_type)
512 {
513 nsCString uri;
514 rv = mNC_FileSystemObject->GetValueUTF8(uri);
515 if (NS_FAILED(rv)) return rv;
516
517 NS_ConvertUTF8toUTF16 url(uri);
518
519 nsCOMPtr<nsIRDFLiteral> literal;
520 rv = mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
521 if (NS_FAILED(rv)) return rv;
522
523 return NS_NewSingletonEnumerator(targets, literal);
524 }
525 else if (property == mNC_pulse)
526 {
527 nsCOMPtr<nsIRDFLiteral> pulseLiteral;
528 rv = mRDFService->GetLiteral(u"12",
529 getter_AddRefs(pulseLiteral));
530 if (NS_FAILED(rv)) return rv;
531
532 return NS_NewSingletonEnumerator(targets, pulseLiteral);
533 }
534 }
535
536 return NS_NewEmptyEnumerator(targets);
537 }
538
539
540
541 NS_IMETHODIMP
Assert(nsIRDFResource * source,nsIRDFResource * property,nsIRDFNode * target,bool tv)542 FileSystemDataSource::Assert(nsIRDFResource *source,
543 nsIRDFResource *property,
544 nsIRDFNode *target,
545 bool tv)
546 {
547 return NS_RDF_ASSERTION_REJECTED;
548 }
549
550
551
552 NS_IMETHODIMP
Unassert(nsIRDFResource * source,nsIRDFResource * property,nsIRDFNode * target)553 FileSystemDataSource::Unassert(nsIRDFResource *source,
554 nsIRDFResource *property,
555 nsIRDFNode *target)
556 {
557 return NS_RDF_ASSERTION_REJECTED;
558 }
559
560
561
562 NS_IMETHODIMP
Change(nsIRDFResource * aSource,nsIRDFResource * aProperty,nsIRDFNode * aOldTarget,nsIRDFNode * aNewTarget)563 FileSystemDataSource::Change(nsIRDFResource* aSource,
564 nsIRDFResource* aProperty,
565 nsIRDFNode* aOldTarget,
566 nsIRDFNode* aNewTarget)
567 {
568 return NS_RDF_ASSERTION_REJECTED;
569 }
570
571
572
573 NS_IMETHODIMP
Move(nsIRDFResource * aOldSource,nsIRDFResource * aNewSource,nsIRDFResource * aProperty,nsIRDFNode * aTarget)574 FileSystemDataSource::Move(nsIRDFResource* aOldSource,
575 nsIRDFResource* aNewSource,
576 nsIRDFResource* aProperty,
577 nsIRDFNode* aTarget)
578 {
579 return NS_RDF_ASSERTION_REJECTED;
580 }
581
582
583
584 NS_IMETHODIMP
HasAssertion(nsIRDFResource * source,nsIRDFResource * property,nsIRDFNode * target,bool tv,bool * hasAssertion)585 FileSystemDataSource::HasAssertion(nsIRDFResource *source,
586 nsIRDFResource *property,
587 nsIRDFNode *target,
588 bool tv,
589 bool *hasAssertion /* out */)
590 {
591 NS_PRECONDITION(source != nullptr, "null ptr");
592 if (! source)
593 return NS_ERROR_NULL_POINTER;
594
595 NS_PRECONDITION(property != nullptr, "null ptr");
596 if (! property)
597 return NS_ERROR_NULL_POINTER;
598
599 NS_PRECONDITION(target != nullptr, "null ptr");
600 if (! target)
601 return NS_ERROR_NULL_POINTER;
602
603 NS_PRECONDITION(hasAssertion != nullptr, "null ptr");
604 if (! hasAssertion)
605 return NS_ERROR_NULL_POINTER;
606
607 // we only have positive assertions in the file system data source.
608 *hasAssertion = false;
609
610 if (! tv) {
611 return NS_OK;
612 }
613
614 if ((source == mNC_FileSystemRoot) || isFileURI(source))
615 {
616 if (property == mRDF_type)
617 {
618 nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(target) );
619 if (resource.get() == mRDF_type)
620 {
621 *hasAssertion = true;
622 }
623 }
624 #ifdef USE_NC_EXTENSION
625 else if (property == mNC_extension)
626 {
627 // Cheat just a little here by making dirs always match
628 if (isDirURI(source))
629 {
630 *hasAssertion = true;
631 }
632 else
633 {
634 nsCOMPtr<nsIRDFLiteral> extension;
635 GetExtension(source, getter_AddRefs(extension));
636 if (extension.get() == target)
637 {
638 *hasAssertion = true;
639 }
640 }
641 }
642 #endif
643 else if (property == mNC_IsDirectory)
644 {
645 bool isDir = isDirURI(source);
646 bool isEqual = false;
647 target->EqualsNode(mLiteralTrue, &isEqual);
648 if (isEqual)
649 {
650 *hasAssertion = isDir;
651 }
652 else
653 {
654 target->EqualsNode(mLiteralFalse, &isEqual);
655 if (isEqual)
656 *hasAssertion = !isDir;
657 }
658 }
659 }
660
661 return NS_OK;
662 }
663
664
665
666 NS_IMETHODIMP
HasArcIn(nsIRDFNode * aNode,nsIRDFResource * aArc,bool * result)667 FileSystemDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
668 {
669 return NS_ERROR_NOT_IMPLEMENTED;
670 }
671
672
673
674 NS_IMETHODIMP
HasArcOut(nsIRDFResource * aSource,nsIRDFResource * aArc,bool * result)675 FileSystemDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
676 {
677 *result = false;
678
679 if (aSource == mNC_FileSystemRoot)
680 {
681 *result = (aArc == mNC_Child || aArc == mNC_pulse);
682 }
683 else if (isFileURI(aSource))
684 {
685 if (aArc == mNC_pulse)
686 {
687 *result = true;
688 }
689 else if (isDirURI(aSource))
690 {
691 #ifdef XP_WIN
692 *result = isValidFolder(aSource);
693 #else
694 *result = true;
695 #endif
696 }
697 else if (aArc == mNC_pulse || aArc == mNC_Name || aArc == mNC_Icon ||
698 aArc == mNC_URL || aArc == mNC_Length || aArc == mWEB_LastMod ||
699 aArc == mNC_FileSystemObject || aArc == mRDF_InstanceOf ||
700 aArc == mRDF_type)
701 {
702 *result = true;
703 }
704 }
705 return NS_OK;
706 }
707
708
709
710 NS_IMETHODIMP
ArcLabelsIn(nsIRDFNode * node,nsISimpleEnumerator ** labels)711 FileSystemDataSource::ArcLabelsIn(nsIRDFNode *node,
712 nsISimpleEnumerator ** labels /* out */)
713 {
714 // NS_NOTYETIMPLEMENTED("write me");
715 return NS_ERROR_NOT_IMPLEMENTED;
716 }
717
718
719
720 NS_IMETHODIMP
ArcLabelsOut(nsIRDFResource * source,nsISimpleEnumerator ** labels)721 FileSystemDataSource::ArcLabelsOut(nsIRDFResource *source,
722 nsISimpleEnumerator **labels /* out */)
723 {
724 NS_PRECONDITION(source != nullptr, "null ptr");
725 if (! source)
726 return NS_ERROR_NULL_POINTER;
727
728 NS_PRECONDITION(labels != nullptr, "null ptr");
729 if (! labels)
730 return NS_ERROR_NULL_POINTER;
731
732 if (source == mNC_FileSystemRoot)
733 {
734 nsCOMArray<nsIRDFResource> resources;
735 resources.SetCapacity(2);
736
737 resources.AppendObject(mNC_Child);
738 resources.AppendObject(mNC_pulse);
739
740 return NS_NewArrayEnumerator(labels, resources);
741 }
742 else if (isFileURI(source))
743 {
744 nsCOMArray<nsIRDFResource> resources;
745 resources.SetCapacity(2);
746
747 if (isDirURI(source))
748 {
749 #ifdef XP_WIN
750 if (isValidFolder(source))
751 {
752 resources.AppendObject(mNC_Child);
753 }
754 #else
755 resources.AppendObject(mNC_Child);
756 #endif
757 resources.AppendObject(mNC_pulse);
758 }
759
760 return NS_NewArrayEnumerator(labels, resources);
761 }
762
763 return NS_NewEmptyEnumerator(labels);
764 }
765
766
767
768 NS_IMETHODIMP
GetAllResources(nsISimpleEnumerator ** aCursor)769 FileSystemDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
770 {
771 NS_NOTYETIMPLEMENTED("sorry!");
772 return NS_ERROR_NOT_IMPLEMENTED;
773 }
774
775
776
777 NS_IMETHODIMP
AddObserver(nsIRDFObserver * n)778 FileSystemDataSource::AddObserver(nsIRDFObserver *n)
779 {
780 return NS_ERROR_NOT_IMPLEMENTED;
781 }
782
783
784
785 NS_IMETHODIMP
RemoveObserver(nsIRDFObserver * n)786 FileSystemDataSource::RemoveObserver(nsIRDFObserver *n)
787 {
788 return NS_ERROR_NOT_IMPLEMENTED;
789 }
790
791
792
793 NS_IMETHODIMP
GetAllCmds(nsIRDFResource * source,nsISimpleEnumerator ** commands)794 FileSystemDataSource::GetAllCmds(nsIRDFResource* source,
795 nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
796 {
797 return(NS_NewEmptyEnumerator(commands));
798 }
799
800
801
802 NS_IMETHODIMP
IsCommandEnabled(nsISupports * aSources,nsIRDFResource * aCommand,nsISupports * aArguments,bool * aResult)803 FileSystemDataSource::IsCommandEnabled(nsISupports/*<nsIRDFResource>*/* aSources,
804 nsIRDFResource* aCommand,
805 nsISupports/*<nsIRDFResource>*/* aArguments,
806 bool* aResult)
807 {
808 return(NS_ERROR_NOT_IMPLEMENTED);
809 }
810
811
812
813 NS_IMETHODIMP
DoCommand(nsISupports * aSources,nsIRDFResource * aCommand,nsISupports * aArguments)814 FileSystemDataSource::DoCommand(nsISupports/*<nsIRDFResource>*/* aSources,
815 nsIRDFResource* aCommand,
816 nsISupports/*<nsIRDFResource>*/* aArguments)
817 {
818 return(NS_ERROR_NOT_IMPLEMENTED);
819 }
820
821
822
823 NS_IMETHODIMP
BeginUpdateBatch()824 FileSystemDataSource::BeginUpdateBatch()
825 {
826 return NS_OK;
827 }
828
829
830
831 NS_IMETHODIMP
EndUpdateBatch()832 FileSystemDataSource::EndUpdateBatch()
833 {
834 return NS_OK;
835 }
836
837
838
839 nsresult
GetVolumeList(nsISimpleEnumerator ** aResult)840 FileSystemDataSource::GetVolumeList(nsISimpleEnumerator** aResult)
841 {
842 nsCOMArray<nsIRDFResource> volumes;
843 nsCOMPtr<nsIRDFResource> vol;
844
845 #ifdef XP_WIN
846
847 int32_t driveType;
848 wchar_t drive[32];
849 int32_t volNum;
850
851 for (volNum = 0; volNum < 26; volNum++)
852 {
853 swprintf_s(drive, 32, L"%c:\\", volNum + (char16_t)'A');
854
855 driveType = GetDriveTypeW(drive);
856 if (driveType != DRIVE_UNKNOWN && driveType != DRIVE_NO_ROOT_DIR)
857 {
858 nsAutoCString url;
859 url.AppendPrintf("file:///%c|/", volNum + 'A');
860 nsresult rv = mRDFService->GetResource(url, getter_AddRefs(vol));
861 if (NS_FAILED(rv))
862 return rv;
863
864 volumes.AppendObject(vol);
865 }
866 }
867 #endif
868
869 #ifdef XP_UNIX
870 mRDFService->GetResource(NS_LITERAL_CSTRING("file:///"), getter_AddRefs(vol));
871 volumes.AppendObject(vol);
872 #endif
873
874 return NS_NewArrayEnumerator(aResult, volumes);
875 }
876
877
878
879 #ifdef XP_WIN
880 bool
isValidFolder(nsIRDFResource * source)881 FileSystemDataSource::isValidFolder(nsIRDFResource *source)
882 {
883 bool isValid = true;
884 if (ieFavoritesDir.IsEmpty()) return(isValid);
885
886 nsresult rv;
887 nsCString uri;
888 rv = source->GetValueUTF8(uri);
889 if (NS_FAILED(rv)) return(isValid);
890
891 NS_ConvertUTF8toUTF16 theURI(uri);
892 if (theURI.Find(ieFavoritesDir) == 0)
893 {
894 isValid = false;
895
896 nsCOMPtr<nsISimpleEnumerator> folderEnum;
897 if (NS_SUCCEEDED(rv = GetFolderList(source, true, false, getter_AddRefs(folderEnum))))
898 {
899 bool hasAny = false, hasMore;
900 while (NS_SUCCEEDED(folderEnum->HasMoreElements(&hasMore)) &&
901 hasMore)
902 {
903 hasAny = true;
904
905 nsCOMPtr<nsISupports> isupports;
906 if (NS_FAILED(rv = folderEnum->GetNext(getter_AddRefs(isupports))))
907 break;
908 nsCOMPtr<nsIRDFResource> res = do_QueryInterface(isupports);
909 if (!res) break;
910
911 nsCOMPtr<nsIRDFLiteral> nameLiteral;
912 if (NS_FAILED(rv = GetName(res, getter_AddRefs(nameLiteral))))
913 break;
914
915 const char16_t *uniName;
916 if (NS_FAILED(rv = nameLiteral->GetValueConst(&uniName)))
917 break;
918 nsAutoString name(uniName);
919
920 // An empty folder, or a folder that contains just "desktop.ini",
921 // is considered to be a IE Favorite; otherwise, its a folder
922 if (!name.LowerCaseEqualsLiteral("desktop.ini"))
923 {
924 isValid = true;
925 break;
926 }
927 }
928 if (!hasAny) isValid = true;
929 }
930 }
931 return(isValid);
932 }
933 #endif
934
935
936
937 nsresult
GetFolderList(nsIRDFResource * source,bool allowHidden,bool onlyFirst,nsISimpleEnumerator ** aResult)938 FileSystemDataSource::GetFolderList(nsIRDFResource *source, bool allowHidden,
939 bool onlyFirst, nsISimpleEnumerator** aResult)
940 {
941 if (!isDirURI(source))
942 return(NS_RDF_NO_VALUE);
943
944 nsresult rv;
945
946 const char *parentURI = nullptr;
947 rv = source->GetValueConst(&parentURI);
948 if (NS_FAILED(rv))
949 return(rv);
950 if (!parentURI)
951 return(NS_ERROR_UNEXPECTED);
952
953 nsCOMPtr<nsIURI> aIURI;
954 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(parentURI))))
955 return(rv);
956
957 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
958 if (!fileURL)
959 return NS_OK;
960
961 nsCOMPtr<nsIFile> aDir;
962 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aDir))))
963 return(rv);
964
965 // ensure that we DO NOT resolve aliases
966 aDir->SetFollowLinks(false);
967
968 nsCOMPtr<nsISimpleEnumerator> dirContents;
969 if (NS_FAILED(rv = aDir->GetDirectoryEntries(getter_AddRefs(dirContents))))
970 return(rv);
971 if (!dirContents)
972 return(NS_ERROR_UNEXPECTED);
973
974 nsCOMArray<nsIRDFResource> resources;
975 bool hasMore;
976 while(NS_SUCCEEDED(rv = dirContents->HasMoreElements(&hasMore)) &&
977 hasMore)
978 {
979 nsCOMPtr<nsISupports> isupports;
980 if (NS_FAILED(rv = dirContents->GetNext(getter_AddRefs(isupports))))
981 break;
982
983 nsCOMPtr<nsIFile> aFile = do_QueryInterface(isupports);
984 if (!aFile)
985 break;
986
987 if (!allowHidden)
988 {
989 bool hiddenFlag = false;
990 if (NS_FAILED(rv = aFile->IsHidden(&hiddenFlag)))
991 break;
992 if (hiddenFlag)
993 continue;
994 }
995
996 nsAutoString leafStr;
997 if (NS_FAILED(rv = aFile->GetLeafName(leafStr)))
998 break;
999 if (leafStr.IsEmpty())
1000 continue;
1001
1002 nsAutoCString fullURI;
1003 fullURI.Assign(parentURI);
1004 if (fullURI.Last() != '/')
1005 {
1006 fullURI.Append('/');
1007 }
1008
1009 nsAutoCString leaf;
1010 bool escaped = NS_Escape(NS_ConvertUTF16toUTF8(leafStr), leaf, url_Path);
1011 leafStr.Truncate();
1012
1013 if (!escaped) {
1014 continue;
1015 }
1016
1017 // using nsEscape() [above] doesn't escape slashes, so do that by hand
1018 int32_t aOffset;
1019 while ((aOffset = leaf.FindChar('/')) >= 0)
1020 {
1021 leaf.Cut((uint32_t)aOffset, 1);
1022 leaf.Insert("%2F", (uint32_t)aOffset);
1023 }
1024
1025 // append the encoded name
1026 fullURI.Append(leaf);
1027
1028 bool dirFlag = false;
1029 rv = aFile->IsDirectory(&dirFlag);
1030 if (NS_SUCCEEDED(rv) && dirFlag)
1031 {
1032 fullURI.Append('/');
1033 }
1034
1035 nsCOMPtr<nsIRDFResource> fileRes;
1036 mRDFService->GetResource(fullURI, getter_AddRefs(fileRes));
1037
1038 resources.AppendObject(fileRes);
1039
1040 if (onlyFirst)
1041 break;
1042 }
1043
1044 return NS_NewArrayEnumerator(aResult, resources);
1045 }
1046
1047 nsresult
GetLastMod(nsIRDFResource * source,nsIRDFDate ** aResult)1048 FileSystemDataSource::GetLastMod(nsIRDFResource *source, nsIRDFDate **aResult)
1049 {
1050 *aResult = nullptr;
1051
1052 nsresult rv;
1053 const char *uri = nullptr;
1054
1055 rv = source->GetValueConst(&uri);
1056 if (NS_FAILED(rv)) return(rv);
1057 if (!uri)
1058 return(NS_ERROR_UNEXPECTED);
1059
1060 nsCOMPtr<nsIURI> aIURI;
1061 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1062 return(rv);
1063
1064 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1065 if (!fileURL)
1066 return NS_OK;
1067
1068 nsCOMPtr<nsIFile> aFile;
1069 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1070 return(rv);
1071 if (!aFile)
1072 return(NS_ERROR_UNEXPECTED);
1073
1074 // ensure that we DO NOT resolve aliases
1075 aFile->SetFollowLinks(false);
1076
1077 PRTime lastModDate;
1078 if (NS_FAILED(rv = aFile->GetLastModifiedTime(&lastModDate)))
1079 return(rv);
1080
1081 // convert from milliseconds to seconds
1082 mRDFService->GetDateLiteral(lastModDate * PR_MSEC_PER_SEC, aResult);
1083
1084 return(NS_OK);
1085 }
1086
1087
1088
1089 nsresult
GetFileSize(nsIRDFResource * source,nsIRDFInt ** aResult)1090 FileSystemDataSource::GetFileSize(nsIRDFResource *source, nsIRDFInt **aResult)
1091 {
1092 *aResult = nullptr;
1093
1094 nsresult rv;
1095 const char *uri = nullptr;
1096
1097 rv = source->GetValueConst(&uri);
1098 if (NS_FAILED(rv))
1099 return(rv);
1100 if (!uri)
1101 return(NS_ERROR_UNEXPECTED);
1102
1103 nsCOMPtr<nsIURI> aIURI;
1104 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1105 return(rv);
1106
1107 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1108 if (!fileURL)
1109 return NS_OK;
1110
1111 nsCOMPtr<nsIFile> aFile;
1112 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1113 return(rv);
1114 if (!aFile)
1115 return(NS_ERROR_UNEXPECTED);
1116
1117 // ensure that we DO NOT resolve aliases
1118 aFile->SetFollowLinks(false);
1119
1120 // don't do anything with directories
1121 bool isDir = false;
1122 if (NS_FAILED(rv = aFile->IsDirectory(&isDir)))
1123 return(rv);
1124 if (isDir)
1125 return(NS_RDF_NO_VALUE);
1126
1127 int64_t aFileSize64;
1128 if (NS_FAILED(rv = aFile->GetFileSize(&aFileSize64)))
1129 return(rv);
1130
1131 // convert 64bits to 32bits
1132 int32_t aFileSize32 = int32_t(aFileSize64);
1133 mRDFService->GetIntLiteral(aFileSize32, aResult);
1134
1135 return(NS_OK);
1136 }
1137
1138
1139
1140 nsresult
GetName(nsIRDFResource * source,nsIRDFLiteral ** aResult)1141 FileSystemDataSource::GetName(nsIRDFResource *source, nsIRDFLiteral **aResult)
1142 {
1143 nsresult rv;
1144 const char *uri = nullptr;
1145
1146 rv = source->GetValueConst(&uri);
1147 if (NS_FAILED(rv))
1148 return(rv);
1149 if (!uri)
1150 return(NS_ERROR_UNEXPECTED);
1151
1152 nsCOMPtr<nsIURI> aIURI;
1153 if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
1154 return(rv);
1155
1156 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aIURI);
1157 if (!fileURL)
1158 return NS_OK;
1159
1160 nsCOMPtr<nsIFile> aFile;
1161 if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
1162 return(rv);
1163 if (!aFile)
1164 return(NS_ERROR_UNEXPECTED);
1165
1166 // ensure that we DO NOT resolve aliases
1167 aFile->SetFollowLinks(false);
1168
1169 nsAutoString name;
1170 if (NS_FAILED(rv = aFile->GetLeafName(name)))
1171 return(rv);
1172 if (name.IsEmpty())
1173 return(NS_ERROR_UNEXPECTED);
1174
1175 #ifdef XP_WIN
1176 // special hack for IE favorites under Windows; strip off the
1177 // trailing ".url" or ".lnk" at the end of IE favorites names
1178 int32_t nameLen = name.Length();
1179 if ((strncmp(uri, ieFavoritesDir.get(), ieFavoritesDir.Length()) == 0) && (nameLen > 4))
1180 {
1181 nsAutoString extension;
1182 name.Right(extension, 4);
1183 if (extension.LowerCaseEqualsLiteral(".url") ||
1184 extension.LowerCaseEqualsLiteral(".lnk"))
1185 {
1186 name.Truncate(nameLen - 4);
1187 }
1188 }
1189 #endif
1190
1191 mRDFService->GetLiteral(name.get(), aResult);
1192
1193 return NS_OK;
1194 }
1195
1196
1197
1198 #ifdef USE_NC_EXTENSION
1199 nsresult
GetExtension(nsIRDFResource * source,nsIRDFLiteral ** aResult)1200 FileSystemDataSource::GetExtension(nsIRDFResource *source, nsIRDFLiteral **aResult)
1201 {
1202 nsCOMPtr<nsIRDFLiteral> name;
1203 nsresult rv = GetName(source, getter_AddRefs(name));
1204 if (NS_FAILED(rv))
1205 return rv;
1206
1207 const char16_t* unicodeLeafName;
1208 rv = name->GetValueConst(&unicodeLeafName);
1209 if (NS_FAILED(rv))
1210 return rv;
1211
1212 nsAutoString filename(unicodeLeafName);
1213 int32_t lastDot = filename.RFindChar('.');
1214 if (lastDot == -1)
1215 {
1216 mRDFService->GetLiteral(EmptyString().get(), aResult);
1217 }
1218 else
1219 {
1220 nsAutoString extension;
1221 filename.Right(extension, (filename.Length() - lastDot));
1222 mRDFService->GetLiteral(extension.get(), aResult);
1223 }
1224
1225 return NS_OK;
1226 }
1227 #endif
1228
1229 #ifdef XP_WIN
1230 nsresult
getIEFavoriteURL(nsIRDFResource * source,nsString aFileURL,nsIRDFLiteral ** urlLiteral)1231 FileSystemDataSource::getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral)
1232 {
1233 nsresult rv = NS_OK;
1234
1235 *urlLiteral = nullptr;
1236
1237 nsCOMPtr<nsIFile> f;
1238 NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileURL), getter_AddRefs(f));
1239
1240 bool value;
1241
1242 if (NS_SUCCEEDED(f->IsDirectory(&value)) && value)
1243 {
1244 if (isValidFolder(source))
1245 return(NS_RDF_NO_VALUE);
1246 aFileURL.AppendLiteral("desktop.ini");
1247 }
1248 else if (aFileURL.Length() > 4)
1249 {
1250 nsAutoString extension;
1251
1252 aFileURL.Right(extension, 4);
1253 if (!extension.LowerCaseEqualsLiteral(".url"))
1254 {
1255 return(NS_RDF_NO_VALUE);
1256 }
1257 }
1258
1259 nsCOMPtr<nsIInputStream> strm;
1260 NS_NewLocalFileInputStream(getter_AddRefs(strm),f);
1261 nsCOMPtr<nsILineInputStream> linereader = do_QueryInterface(strm, &rv);
1262
1263 nsAutoString line;
1264 nsAutoCString cLine;
1265 while(NS_SUCCEEDED(rv))
1266 {
1267 bool isEOF;
1268 rv = linereader->ReadLine(cLine, &isEOF);
1269 CopyASCIItoUTF16(cLine, line);
1270
1271 if (isEOF)
1272 {
1273 if (line.Find("URL=", true) == 0)
1274 {
1275 line.Cut(0, 4);
1276 rv = mRDFService->GetLiteral(line.get(), urlLiteral);
1277 break;
1278 }
1279 else if (line.Find("CDFURL=", true) == 0)
1280 {
1281 line.Cut(0, 7);
1282 rv = mRDFService->GetLiteral(line.get(), urlLiteral);
1283 break;
1284 }
1285 line.Truncate();
1286 }
1287 }
1288
1289 return(rv);
1290 }
1291 #endif
1292
1293
1294
1295 nsresult
GetURL(nsIRDFResource * source,bool * isFavorite,nsIRDFLiteral ** aResult)1296 FileSystemDataSource::GetURL(nsIRDFResource *source, bool *isFavorite, nsIRDFLiteral** aResult)
1297 {
1298 if (isFavorite) *isFavorite = false;
1299
1300 nsresult rv;
1301 nsCString uri;
1302
1303 rv = source->GetValueUTF8(uri);
1304 if (NS_FAILED(rv))
1305 return(rv);
1306
1307 NS_ConvertUTF8toUTF16 url(uri);
1308
1309 #ifdef XP_WIN
1310 // under Windows, if its an IE favorite, munge the URL
1311 if (!ieFavoritesDir.IsEmpty())
1312 {
1313 if (url.Find(ieFavoritesDir) == 0)
1314 {
1315 if (isFavorite) *isFavorite = true;
1316 rv = getIEFavoriteURL(source, url, aResult);
1317 return(rv);
1318 }
1319 }
1320 #endif
1321
1322 // if we fall through to here, its not any type of bookmark
1323 // stored in the platform native file system, so just set the URL
1324
1325 mRDFService->GetLiteral(url.get(), aResult);
1326
1327 return(NS_OK);
1328 }
1329