Back to index

lightning-sunbird  0.9+nobinonly
nsFileSystemDataSource.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039   Implementation for a file system RDF data store.
00040  */
00041 
00042 #include <ctype.h> // for toupper()
00043 #include <stdio.h>
00044 #include "nscore.h"
00045 #include "nsCOMPtr.h"
00046 #include "nsIEnumerator.h"
00047 #include "nsIRDFDataSource.h"
00048 #include "nsIRDFNode.h"
00049 #include "nsIRDFObserver.h"
00050 #include "nsIServiceManager.h"
00051 #include "nsString.h"
00052 #include "nsVoidArray.h"  // XXX introduces dependency on raptorbase
00053 #include "nsXPIDLString.h"
00054 #include "nsRDFCID.h"
00055 #include "rdfutil.h"
00056 #include "nsIRDFService.h"
00057 #include "plhash.h"
00058 #include "plstr.h"
00059 #include "prlong.h"
00060 #include "prlog.h"
00061 #include "prmem.h"
00062 #include "prprf.h"
00063 #include "prio.h"
00064 #include "rdf.h"
00065 #include "nsIRDFFileSystem.h"
00066 #include "nsEnumeratorUtils.h"
00067 #include "nsIURL.h"
00068 #include "nsIFileURL.h"
00069 #include "nsNetUtil.h"
00070 #include "nsIChannel.h"
00071 #include "nsIFile.h"
00072 #include "nsEscape.h"
00073 #include "nsCRT.h"
00074 
00075 #ifdef  XP_WIN
00076 #include "windef.h"
00077 #include "winbase.h"
00078 #include "nsILineInputStream.h"
00079 #endif
00080 
00081 #ifdef  XP_BEOS
00082 #include <File.h>
00083 #include <NodeInfo.h>
00084 #endif
00085 
00086 #if defined(XP_WIN) || defined(XP_BEOS)
00087 #include "nsDirectoryServiceDefs.h"
00088 #endif
00089 
00090 #ifdef XP_OS2
00091 #define INCL_DOSFILEMGR
00092 #include <os2.h>
00093 #endif
00094 
00095 #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_WIN)
00096 #define USE_NC_EXTENSION
00097 #endif
00098 
00099 static NS_DEFINE_CID(kRDFServiceCID,               NS_RDFSERVICE_CID);
00100 
00101 #define NS_MOZICON_SCHEME           "moz-icon:"
00102 
00103 static const char kFileProtocol[]         = "file://";
00104 
00105 
00106 
00107 class FileSystemDataSource : public nsIRDFFileSystemDataSource
00108 {
00109 private:
00110     nsCOMPtr<nsISupportsArray> mObservers;
00111 
00112     static PRInt32 gRefCnt;
00113 
00114     // pseudo-constants
00115     static nsIRDFResource       *kNC_FileSystemRoot;
00116     static nsIRDFResource       *kNC_Child;
00117     static nsIRDFResource       *kNC_Name;
00118     static nsIRDFResource       *kNC_URL;
00119     static nsIRDFResource       *kNC_Icon;
00120     static nsIRDFResource       *kNC_Length;
00121     static nsIRDFResource       *kNC_IsDirectory;
00122     static nsIRDFResource       *kWEB_LastMod;
00123     static nsIRDFResource       *kNC_FileSystemObject;
00124     static nsIRDFResource       *kNC_pulse;
00125     static nsIRDFResource       *kRDF_InstanceOf;
00126     static nsIRDFResource       *kRDF_type;
00127 
00128 #ifdef USE_NC_EXTENSION
00129     static nsIRDFResource       *kNC_extension;
00130 #endif
00131 
00132 #ifdef  XP_WIN
00133     static nsIRDFResource       *kNC_IEFavoriteObject;
00134     static nsIRDFResource       *kNC_IEFavoriteFolder;
00135     static char                 *ieFavoritesDir;
00136 #endif
00137 
00138 #ifdef  XP_BEOS
00139     static nsIRDFResource       *kNC_NetPositiveObject;
00140     static char                 *netPositiveDir;
00141 #endif
00142 
00143     static nsIRDFLiteral        *kLiteralTrue;
00144     static nsIRDFLiteral        *kLiteralFalse;
00145 
00146 public:
00147 
00148     NS_DECL_ISUPPORTS
00149 
00150     FileSystemDataSource(void);
00151     virtual     ~FileSystemDataSource(void);
00152 
00153     // nsIRDFDataSource methods
00154     NS_DECL_NSIRDFDATASOURCE
00155 
00156     // helper methods
00157     static PRBool   isFileURI(nsIRDFResource* aResource);
00158     static PRBool   isDirURI(nsIRDFResource* aSource);
00159     static nsresult GetVolumeList(nsISimpleEnumerator **aResult);
00160     static nsresult GetFolderList(nsIRDFResource *source, PRBool allowHidden, PRBool onlyFirst, nsISimpleEnumerator **aResult);
00161     static nsresult GetName(nsIRDFResource *source, nsIRDFLiteral** aResult);
00162     static nsresult GetURL(nsIRDFResource *source, PRBool *isFavorite, nsIRDFLiteral** aResult);
00163     static nsresult GetFileSize(nsIRDFResource *source, nsIRDFInt** aResult);
00164     static nsresult GetLastMod(nsIRDFResource *source, nsIRDFDate** aResult);
00165 
00166 #ifdef USE_NC_EXTENSION
00167     static nsresult GetExtension(nsIRDFResource *source, nsIRDFLiteral** aResult);
00168 #endif
00169 
00170 #ifdef  XP_WIN
00171     static PRBool   isValidFolder(nsIRDFResource *source);
00172     static nsresult getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral);
00173 #endif
00174 
00175 #ifdef  XP_BEOS
00176     static nsresult getNetPositiveURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral);
00177 #endif
00178 
00179 };
00180 
00181 
00182 
00183 static  nsIRDFService         *gRDFService = nsnull;
00184 static  FileSystemDataSource  *gFileSystemDataSource = nsnull;
00185 
00186 PRInt32 FileSystemDataSource::gRefCnt;
00187 
00188 nsIRDFResource      *FileSystemDataSource::kNC_FileSystemRoot;
00189 nsIRDFResource      *FileSystemDataSource::kNC_Child;
00190 nsIRDFResource      *FileSystemDataSource::kNC_Name;
00191 nsIRDFResource      *FileSystemDataSource::kNC_URL;
00192 nsIRDFResource      *FileSystemDataSource::kNC_Icon;
00193 nsIRDFResource      *FileSystemDataSource::kNC_Length;
00194 nsIRDFResource      *FileSystemDataSource::kNC_IsDirectory;
00195 nsIRDFResource      *FileSystemDataSource::kWEB_LastMod;
00196 nsIRDFResource      *FileSystemDataSource::kNC_FileSystemObject;
00197 nsIRDFResource      *FileSystemDataSource::kNC_pulse;
00198 nsIRDFResource      *FileSystemDataSource::kRDF_InstanceOf;
00199 nsIRDFResource      *FileSystemDataSource::kRDF_type;
00200 nsIRDFLiteral       *FileSystemDataSource::kLiteralTrue;
00201 nsIRDFLiteral       *FileSystemDataSource::kLiteralFalse;
00202 
00203 #ifdef USE_NC_EXTENSION
00204 nsIRDFResource      *FileSystemDataSource::kNC_extension;
00205 #endif
00206 
00207 #ifdef  XP_WIN
00208 nsIRDFResource      *FileSystemDataSource::kNC_IEFavoriteObject;
00209 nsIRDFResource      *FileSystemDataSource::kNC_IEFavoriteFolder;
00210 char                *FileSystemDataSource::ieFavoritesDir;
00211 #endif
00212 
00213 #ifdef  XP_BEOS
00214 nsIRDFResource      *FileSystemDataSource::kNC_NetPositiveObject;
00215 char                *FileSystemDataSource::netPositiveDir;
00216 #endif
00217 
00218 
00219 
00220 PRBool
00221 FileSystemDataSource::isFileURI(nsIRDFResource *r)
00222 {
00223     PRBool      isFileURIFlag = PR_FALSE;
00224     const char  *uri = nsnull;
00225     
00226     r->GetValueConst(&uri);
00227     if ((uri) && (!strncmp(uri, kFileProtocol, sizeof(kFileProtocol) - 1)))
00228     {
00229         // XXX HACK HACK HACK
00230         if (!strchr(uri, '#'))
00231         {
00232             isFileURIFlag = PR_TRUE;
00233         }
00234     }
00235     return(isFileURIFlag);
00236 }
00237 
00238 
00239 
00240 PRBool
00241 FileSystemDataSource::isDirURI(nsIRDFResource* source)
00242 {
00243     nsresult    rv;
00244     const char  *uri = nsnull;
00245 
00246     rv = source->GetValueConst(&uri);
00247     if (NS_FAILED(rv)) return(PR_FALSE);
00248 
00249     nsCOMPtr<nsIFile> aDir;
00250 
00251     rv = NS_GetFileFromURLSpec(nsDependentCString(uri), getter_AddRefs(aDir));
00252     if (NS_FAILED(rv)) return(PR_FALSE);
00253 
00254     PRBool isDirFlag = PR_FALSE;
00255 
00256     rv = aDir->IsDirectory(&isDirFlag);
00257     if (NS_FAILED(rv)) return(PR_FALSE);
00258 
00259 #ifdef  XP_MAC
00260     // Hide directory structure of packages under Mac OS 9/X
00261     nsCOMPtr<nsILocalFileMac>   aMacFile = do_QueryInterface(aDir);
00262     if (aMacFile)
00263     {
00264         PRBool isPackageFlag = PR_FALSE;
00265         rv = aMacFile->IsPackage(&isPackageFlag);
00266         if (NS_SUCCEEDED(rv) && (isPackageFlag == PR_TRUE))
00267         {
00268             isDirFlag = PR_FALSE;
00269         }
00270     }
00271 #endif
00272 
00273     return(isDirFlag);
00274 }
00275 
00276 
00277 
00278 FileSystemDataSource::FileSystemDataSource(void)
00279 {
00280     if (gRefCnt++ == 0)
00281     {
00282 #ifdef DEBUG
00283         nsresult rv =
00284 #endif
00285         CallGetService(kRDFServiceCID, &gRDFService);
00286 
00287         PR_ASSERT(NS_SUCCEEDED(rv));
00288 
00289 #ifdef  XP_WIN
00290         nsCOMPtr<nsIFile> file;
00291         NS_GetSpecialDirectory(NS_WIN_FAVORITES_DIR, getter_AddRefs(file));
00292         if (file)
00293         {
00294             nsCOMPtr<nsIURI> furi;
00295             NS_NewFileURI(getter_AddRefs(furi), file); 
00296             nsCAutoString favoritesDir;
00297             file->GetNativePath(favoritesDir);
00298             ieFavoritesDir = ToNewCString(favoritesDir);
00299 
00300             gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavorite"),
00301                                      &kNC_IEFavoriteObject);
00302             gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IEFavoriteFolder"),
00303                                      &kNC_IEFavoriteFolder);
00304         }
00305 
00306 #endif
00307 
00308 #ifdef XP_BEOS
00309 
00310         nsCOMPtr<nsIFile> file;
00311         NS_GetSpecialDirectory(NS_BEOS_SETTINGS_DIR, getter_AddRefs(file));
00312 
00313         file->AppendNative(NS_LITERAL_CSTRING("NetPositive"));
00314         file->AppendNative(NS_LITERAL_CSTRING("Bookmarks"));
00315 
00316         nsCOMPtr<nsIURI> furi;
00317         NS_NewFileURI(getter_AddRefs(furi), file); 
00318         nsCAutoString favoritesDir;
00319         file->GetNativePath(favoritesDir);
00320         netPositiveDir = ToNewCString(favoritesDir);
00321 
00322 #endif
00323 
00324         gRDFService->GetResource(NS_LITERAL_CSTRING("NC:FilesRoot"),
00325                                  &kNC_FileSystemRoot);
00326         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "child"),
00327                                  &kNC_Child);
00328         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "Name"),
00329                                  &kNC_Name);
00330         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "URL"),
00331                                  &kNC_URL);
00332         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "Icon"),
00333                                  &kNC_Icon);
00334         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "Content-Length"),
00335                                  &kNC_Length);
00336         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "IsDirectory"),
00337                                  &kNC_IsDirectory);
00338         gRDFService->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
00339                                  &kWEB_LastMod);
00340         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "FileSystemObject"),
00341                                  &kNC_FileSystemObject);
00342         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI  "pulse"),
00343                                  &kNC_pulse);
00344 
00345         gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
00346                                  &kRDF_InstanceOf);
00347         gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
00348                                  &kRDF_type);
00349 
00350 #ifdef USE_NC_EXTENSION
00351         gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "extension"),
00352                                  &kNC_extension);
00353 #endif
00354         gRDFService->GetLiteral(NS_LITERAL_STRING("true").get(),       &kLiteralTrue);
00355         gRDFService->GetLiteral(NS_LITERAL_STRING("false").get(),      &kLiteralFalse);
00356         gFileSystemDataSource = this;
00357     }
00358 }
00359 
00360 
00361 
00362 FileSystemDataSource::~FileSystemDataSource (void)
00363 {
00364 #ifdef DEBUG_REFS
00365     --gInstanceCount;
00366     fprintf(stdout, "%d - RDF: FileSystemDataSource\n", gInstanceCount);
00367 #endif
00368 
00369     if (--gRefCnt == 0) {
00370         NS_RELEASE(kNC_FileSystemRoot);
00371         NS_RELEASE(kNC_Child);
00372         NS_RELEASE(kNC_Name);
00373         NS_RELEASE(kNC_URL);
00374         NS_RELEASE(kNC_Icon);
00375         NS_RELEASE(kNC_Length);
00376         NS_RELEASE(kNC_IsDirectory);
00377         NS_RELEASE(kWEB_LastMod);
00378         NS_RELEASE(kNC_FileSystemObject);
00379         NS_RELEASE(kNC_pulse);
00380         NS_RELEASE(kRDF_InstanceOf);
00381         NS_RELEASE(kRDF_type);
00382 
00383 #ifdef  XP_WIN
00384         NS_IF_RELEASE(kNC_IEFavoriteObject);
00385         NS_IF_RELEASE(kNC_IEFavoriteFolder);
00386 
00387         if (ieFavoritesDir)
00388         {
00389             nsMemory::Free(ieFavoritesDir);
00390             ieFavoritesDir = nsnull;
00391         }
00392 #endif
00393 
00394 #ifdef BEOS
00395 
00396         if (netPositiveDir)
00397         {
00398             nsMemory::Free(netPositiveDir);
00399             netPositiveDir = nsnull;
00400         }
00401 #endif
00402 #ifdef USE_NC_EXTENSION
00403         NS_RELEASE(kNC_extension);
00404 #endif
00405 
00406         NS_RELEASE(kLiteralTrue);
00407         NS_RELEASE(kLiteralFalse);
00408 
00409         gFileSystemDataSource = nsnull;
00410         NS_RELEASE(gRDFService);
00411     }
00412 }
00413 
00414 
00415 
00416 NS_IMPL_ISUPPORTS1(FileSystemDataSource, nsIRDFDataSource)
00417 
00418 
00419 
00420 NS_IMETHODIMP
00421 FileSystemDataSource::GetURI(char **uri)
00422 {
00423     NS_PRECONDITION(uri != nsnull, "null ptr");
00424     if (! uri)
00425         return NS_ERROR_NULL_POINTER;
00426 
00427     if ((*uri = nsCRT::strdup("rdf:files")) == nsnull)
00428         return NS_ERROR_OUT_OF_MEMORY;
00429 
00430     return NS_OK;
00431 }
00432 
00433 
00434 
00435 NS_IMETHODIMP
00436 FileSystemDataSource::GetSource(nsIRDFResource* property,
00437                                 nsIRDFNode* target,
00438                                 PRBool tv,
00439                                 nsIRDFResource** source /* out */)
00440 {
00441     NS_PRECONDITION(property != nsnull, "null ptr");
00442     if (! property)
00443         return NS_ERROR_NULL_POINTER;
00444 
00445     NS_PRECONDITION(target != nsnull, "null ptr");
00446     if (! target)
00447         return NS_ERROR_NULL_POINTER;
00448 
00449     NS_PRECONDITION(source != nsnull, "null ptr");
00450     if (! source)
00451         return NS_ERROR_NULL_POINTER;
00452 
00453     *source = nsnull;
00454     return NS_RDF_NO_VALUE;
00455 }
00456 
00457 
00458 
00459 NS_IMETHODIMP
00460 FileSystemDataSource::GetSources(nsIRDFResource *property,
00461                                  nsIRDFNode *target,
00462                                  PRBool tv,
00463                                  nsISimpleEnumerator **sources /* out */)
00464 {
00465 //  NS_NOTYETIMPLEMENTED("write me");
00466     return NS_ERROR_NOT_IMPLEMENTED;
00467 }
00468 
00469 
00470 
00471 NS_IMETHODIMP
00472 FileSystemDataSource::GetTarget(nsIRDFResource *source,
00473                                 nsIRDFResource *property,
00474                                 PRBool tv,
00475                                 nsIRDFNode **target /* out */)
00476 {
00477     NS_PRECONDITION(source != nsnull, "null ptr");
00478     if (! source)
00479         return NS_ERROR_NULL_POINTER;
00480 
00481     NS_PRECONDITION(property != nsnull, "null ptr");
00482     if (! property)
00483         return NS_ERROR_NULL_POINTER;
00484 
00485     NS_PRECONDITION(target != nsnull, "null ptr");
00486     if (! target)
00487         return NS_ERROR_NULL_POINTER;
00488 
00489     *target = nsnull;
00490 
00491     nsresult        rv = NS_RDF_NO_VALUE;
00492 
00493     // we only have positive assertions in the file system data source.
00494     if (! tv)
00495         return NS_RDF_NO_VALUE;
00496 
00497     if (source == kNC_FileSystemRoot)
00498     {
00499         if (property == kNC_pulse)
00500         {
00501             nsIRDFLiteral   *pulseLiteral;
00502             gRDFService->GetLiteral(NS_LITERAL_STRING("12").get(), &pulseLiteral);
00503             *target = pulseLiteral;
00504             return NS_OK;
00505         }
00506     }
00507     else if (isFileURI(source))
00508     {
00509         if (property == kNC_Name)
00510         {
00511             nsCOMPtr<nsIRDFLiteral> name;
00512             rv = GetName(source, getter_AddRefs(name));
00513             if (NS_FAILED(rv)) return(rv);
00514             if (!name)  rv = NS_RDF_NO_VALUE;
00515             if (rv == NS_RDF_NO_VALUE)  return(rv);
00516             return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00517         }
00518         else if (property == kNC_URL)
00519         {
00520             nsCOMPtr<nsIRDFLiteral> url;
00521             rv = GetURL(source, nsnull, getter_AddRefs(url));
00522             if (NS_FAILED(rv)) return(rv);
00523             if (!url)   rv = NS_RDF_NO_VALUE;
00524             if (rv == NS_RDF_NO_VALUE)  return(rv);
00525 
00526             return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00527         }
00528         else if (property == kNC_Icon)
00529         {
00530             nsCOMPtr<nsIRDFLiteral> url;
00531             PRBool isFavorite = PR_FALSE;
00532             rv = GetURL(source, &isFavorite, getter_AddRefs(url));
00533             if (NS_FAILED(rv)) return(rv);
00534             if (isFavorite || !url) rv = NS_RDF_NO_VALUE;
00535             if (rv == NS_RDF_NO_VALUE)  return(rv);
00536             
00537             const PRUnichar *uni = nsnull;
00538             url->GetValueConst(&uni);
00539             if (!uni)   return(NS_RDF_NO_VALUE);
00540             nsAutoString    urlStr;
00541             urlStr.Assign(NS_LITERAL_STRING(NS_MOZICON_SCHEME).get());
00542             urlStr.Append(uni);
00543 
00544             rv = gRDFService->GetLiteral(urlStr.get(), getter_AddRefs(url));
00545             if (NS_FAILED(rv) || !url)    return(NS_RDF_NO_VALUE);
00546             return url->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00547         }
00548         else if (property == kNC_Length)
00549         {
00550             nsCOMPtr<nsIRDFInt> fileSize;
00551             rv = GetFileSize(source, getter_AddRefs(fileSize));
00552             if (NS_FAILED(rv)) return(rv);
00553             if (!fileSize)  rv = NS_RDF_NO_VALUE;
00554             if (rv == NS_RDF_NO_VALUE)  return(rv);
00555 
00556             return fileSize->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00557         }
00558         else  if (property == kNC_IsDirectory)
00559         {
00560             *target = (isDirURI(source)) ? kLiteralTrue : kLiteralFalse;
00561             NS_ADDREF(*target);
00562             return NS_OK;
00563         }
00564         else if (property == kWEB_LastMod)
00565         {
00566             nsCOMPtr<nsIRDFDate> lastMod;
00567             rv = GetLastMod(source, getter_AddRefs(lastMod));
00568             if (NS_FAILED(rv)) return(rv);
00569             if (!lastMod)   rv = NS_RDF_NO_VALUE;
00570             if (rv == NS_RDF_NO_VALUE)  return(rv);
00571 
00572             return lastMod->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00573         }
00574         else if (property == kRDF_type)
00575         {
00576             nsCString type;
00577             rv = kNC_FileSystemObject->GetValueUTF8(type);
00578             if (NS_FAILED(rv)) return(rv);
00579 
00580 #ifdef  XP_WIN
00581             // under Windows, if its an IE favorite, return that type
00582             if (ieFavoritesDir)
00583             {
00584                 nsCString uri;
00585                 rv = source->GetValueUTF8(uri);
00586                 if (NS_FAILED(rv)) return(rv);
00587 
00588                 NS_ConvertUTF8toUTF16 theURI(uri);
00589 
00590                 if (theURI.Find(ieFavoritesDir) == 0)
00591                 {
00592                     if (theURI[theURI.Length() - 1] == '/')
00593                     {
00594                         rv = kNC_IEFavoriteFolder->GetValueUTF8(type);
00595                     }
00596                     else
00597                     {
00598                         rv = kNC_IEFavoriteObject->GetValueUTF8(type);
00599                     }
00600                     if (NS_FAILED(rv)) return(rv);
00601                 }
00602             }
00603 #endif
00604 
00605             NS_ConvertUTF8toUTF16 url(type);
00606             nsCOMPtr<nsIRDFLiteral> literal;
00607             gRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
00608             rv = literal->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00609             return(rv);
00610         }
00611         else if (property == kNC_pulse)
00612         {
00613             nsCOMPtr<nsIRDFLiteral> pulseLiteral;
00614             gRDFService->GetLiteral(NS_LITERAL_STRING("12").get(), getter_AddRefs(pulseLiteral));
00615             rv = pulseLiteral->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00616             return(rv);
00617         }
00618         else if (property == kNC_Child)
00619         {
00620             // Oh this is evil. Somebody kill me now.
00621             nsCOMPtr<nsISimpleEnumerator> children;
00622             rv = GetFolderList(source, PR_FALSE, PR_TRUE, getter_AddRefs(children));
00623             if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE)) return(rv);
00624 
00625             PRBool hasMore;
00626             rv = children->HasMoreElements(&hasMore);
00627             if (NS_FAILED(rv)) return(rv);
00628 
00629             if (hasMore)
00630             {
00631                 nsCOMPtr<nsISupports> isupports;
00632                 rv = children->GetNext(getter_AddRefs(isupports));
00633                 if (NS_FAILED(rv)) return(rv);
00634 
00635                 return isupports->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00636             }
00637         }
00638 #ifdef USE_NC_EXTENSION
00639         else if (property == kNC_extension)
00640         {
00641             nsCOMPtr<nsIRDFLiteral> extension;
00642             rv = GetExtension(source, getter_AddRefs(extension));
00643             if (!extension)    rv = NS_RDF_NO_VALUE;
00644             if (rv == NS_RDF_NO_VALUE) return(rv);
00645             return extension->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00646         }
00647 #endif
00648     }
00649 
00650     return(NS_RDF_NO_VALUE);
00651 }
00652 
00653 
00654 
00655 NS_IMETHODIMP
00656 FileSystemDataSource::GetTargets(nsIRDFResource *source,
00657                 nsIRDFResource *property,
00658                 PRBool tv,
00659                 nsISimpleEnumerator **targets /* out */)
00660 {
00661     NS_PRECONDITION(source != nsnull, "null ptr");
00662     if (! source)
00663         return NS_ERROR_NULL_POINTER;
00664 
00665     NS_PRECONDITION(property != nsnull, "null ptr");
00666     if (! property)
00667         return NS_ERROR_NULL_POINTER;
00668 
00669     NS_PRECONDITION(targets != nsnull, "null ptr");
00670     if (! targets)
00671         return NS_ERROR_NULL_POINTER;
00672 
00673     *targets = nsnull;
00674 
00675     // we only have positive assertions in the file system data source.
00676     if (! tv)
00677         return NS_RDF_NO_VALUE;
00678 
00679     nsresult rv;
00680 
00681     if (source == kNC_FileSystemRoot)
00682     {
00683         if (property == kNC_Child)
00684         {
00685             return GetVolumeList(targets);
00686         }
00687         else if (property == kNC_pulse)
00688         {
00689             nsIRDFLiteral   *pulseLiteral;
00690             gRDFService->GetLiteral(NS_LITERAL_STRING("12").get(), &pulseLiteral);
00691             nsISimpleEnumerator* result = new nsSingletonEnumerator(pulseLiteral);
00692             NS_RELEASE(pulseLiteral);
00693 
00694             if (! result)
00695                 return NS_ERROR_OUT_OF_MEMORY;
00696 
00697             NS_ADDREF(result);
00698             *targets = result;
00699             return NS_OK;
00700         }
00701     }
00702     else if (isFileURI(source))
00703     {
00704         if (property == kNC_Child)
00705         {
00706             return GetFolderList(source, PR_FALSE, PR_FALSE, targets);
00707         }
00708         else if (property == kNC_Name)
00709         {
00710             nsCOMPtr<nsIRDFLiteral> name;
00711             rv = GetName(source, getter_AddRefs(name));
00712             if (NS_FAILED(rv)) return rv;
00713 
00714             nsISimpleEnumerator* result = new nsSingletonEnumerator(name);
00715             if (! result)
00716                 return NS_ERROR_OUT_OF_MEMORY;
00717 
00718             NS_ADDREF(result);
00719             *targets = result;
00720             return NS_OK;
00721         }
00722         else if (property == kNC_URL)
00723         {
00724             nsCOMPtr<nsIRDFLiteral> url;
00725             rv = GetURL(source, nsnull, getter_AddRefs(url));
00726             if (NS_FAILED(rv)) return rv;
00727 
00728             nsISimpleEnumerator* result = new nsSingletonEnumerator(url);
00729             if (! result)
00730                 return NS_ERROR_OUT_OF_MEMORY;
00731 
00732             NS_ADDREF(result);
00733             *targets = result;
00734             return NS_OK;
00735         }
00736         else if (property == kRDF_type)
00737         {
00738             nsCString uri;
00739             rv = kNC_FileSystemObject->GetValueUTF8(uri);
00740             if (NS_FAILED(rv)) return rv;
00741 
00742             NS_ConvertUTF8toUTF16 url(uri);
00743 
00744             nsCOMPtr<nsIRDFLiteral> literal;
00745             rv = gRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
00746             if (NS_FAILED(rv)) return rv;
00747 
00748             nsISimpleEnumerator* result = new nsSingletonEnumerator(literal);
00749 
00750             if (! result)
00751                 return NS_ERROR_OUT_OF_MEMORY;
00752 
00753             NS_ADDREF(result);
00754             *targets = result;
00755             return NS_OK;
00756         }
00757         else if (property == kNC_pulse)
00758         {
00759             nsCOMPtr<nsIRDFLiteral> pulseLiteral;
00760             rv = gRDFService->GetLiteral(NS_LITERAL_STRING("12").get(),
00761                 getter_AddRefs(pulseLiteral));
00762             if (NS_FAILED(rv)) return rv;
00763 
00764             nsISimpleEnumerator* result = new nsSingletonEnumerator(pulseLiteral);
00765 
00766             if (! result)
00767                 return NS_ERROR_OUT_OF_MEMORY;
00768 
00769             NS_ADDREF(result);
00770             *targets = result;
00771             return NS_OK;
00772         }
00773     }
00774 
00775     return NS_NewEmptyEnumerator(targets);
00776 }
00777 
00778 
00779 
00780 NS_IMETHODIMP
00781 FileSystemDataSource::Assert(nsIRDFResource *source,
00782                        nsIRDFResource *property,
00783                        nsIRDFNode *target,
00784                        PRBool tv)
00785 {
00786     return NS_RDF_ASSERTION_REJECTED;
00787 }
00788 
00789 
00790 
00791 NS_IMETHODIMP
00792 FileSystemDataSource::Unassert(nsIRDFResource *source,
00793                          nsIRDFResource *property,
00794                          nsIRDFNode *target)
00795 {
00796     return NS_RDF_ASSERTION_REJECTED;
00797 }
00798 
00799 
00800 
00801 NS_IMETHODIMP
00802 FileSystemDataSource::Change(nsIRDFResource* aSource,
00803                              nsIRDFResource* aProperty,
00804                              nsIRDFNode* aOldTarget,
00805                              nsIRDFNode* aNewTarget)
00806 {
00807     return NS_RDF_ASSERTION_REJECTED;
00808 }
00809 
00810 
00811 
00812 NS_IMETHODIMP
00813 FileSystemDataSource::Move(nsIRDFResource* aOldSource,
00814                            nsIRDFResource* aNewSource,
00815                            nsIRDFResource* aProperty,
00816                            nsIRDFNode* aTarget)
00817 {
00818     return NS_RDF_ASSERTION_REJECTED;
00819 }
00820 
00821 
00822 
00823 NS_IMETHODIMP
00824 FileSystemDataSource::HasAssertion(nsIRDFResource *source,
00825                              nsIRDFResource *property,
00826                              nsIRDFNode *target,
00827                              PRBool tv,
00828                              PRBool *hasAssertion /* out */)
00829 {
00830     NS_PRECONDITION(source != nsnull, "null ptr");
00831     if (! source)
00832         return NS_ERROR_NULL_POINTER;
00833 
00834     NS_PRECONDITION(property != nsnull, "null ptr");
00835     if (! property)
00836         return NS_ERROR_NULL_POINTER;
00837 
00838     NS_PRECONDITION(target != nsnull, "null ptr");
00839     if (! target)
00840         return NS_ERROR_NULL_POINTER;
00841 
00842     NS_PRECONDITION(hasAssertion != nsnull, "null ptr");
00843     if (! hasAssertion)
00844         return NS_ERROR_NULL_POINTER;
00845 
00846     // we only have positive assertions in the file system data source.
00847     *hasAssertion = PR_FALSE;
00848 
00849     if (! tv) {
00850         return NS_OK;
00851     }
00852 
00853     if ((source == kNC_FileSystemRoot) || isFileURI(source))
00854     {
00855         if (property == kRDF_type)
00856         {
00857             nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(target) );
00858             if (resource.get() == kRDF_type)
00859             {
00860                 *hasAssertion = PR_TRUE;
00861             }
00862         }
00863 #ifdef USE_NC_EXTENSION
00864         else if (property == kNC_extension)
00865         {
00866             // Cheat just a little here by making dirs always match
00867             if (isDirURI(source))
00868             {
00869                 *hasAssertion = PR_TRUE;
00870             }
00871             else
00872             {
00873                 nsCOMPtr<nsIRDFLiteral> extension;
00874                 GetExtension(source, getter_AddRefs(extension));
00875                 if (extension.get() == target)
00876                 {
00877                     *hasAssertion = PR_TRUE;
00878                 }
00879             }
00880         }
00881 #endif
00882         else if (property == kNC_IsDirectory)
00883         {
00884             PRBool isDir = isDirURI(source);
00885             PRBool isEqual = PR_FALSE;
00886             target->EqualsNode(kLiteralTrue, &isEqual);
00887             if (isEqual)
00888             {
00889                 *hasAssertion = isDir;
00890             }
00891             else
00892             {
00893                 target->EqualsNode(kLiteralFalse, &isEqual);
00894                 if (isEqual)
00895                     *hasAssertion = !isDir;
00896             }
00897         }
00898     }
00899 
00900     return NS_OK;
00901 }
00902 
00903 
00904 
00905 NS_IMETHODIMP 
00906 FileSystemDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
00907 {
00908     return NS_ERROR_NOT_IMPLEMENTED;
00909 }
00910 
00911 
00912 
00913 NS_IMETHODIMP 
00914 FileSystemDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, PRBool *result)
00915 {
00916     *result = PR_FALSE;
00917 
00918     if (aSource == kNC_FileSystemRoot)
00919     {
00920         *result = (aArc == kNC_Child || aArc == kNC_pulse);
00921     }
00922     else if (isFileURI(aSource))
00923     {
00924         if (aArc == kNC_pulse)
00925         {
00926             *result = PR_TRUE;
00927         }
00928         else if (isDirURI(aSource))
00929         {
00930 #ifdef  XP_WIN
00931             *result = isValidFolder(aSource);
00932 #else
00933             *result = PR_TRUE;
00934 #endif
00935         }
00936         else if (aArc == kNC_pulse || aArc == kNC_Name || aArc == kNC_Icon ||
00937                  aArc == kNC_URL || aArc == kNC_Length || aArc == kWEB_LastMod ||
00938                  aArc == kNC_FileSystemObject || aArc == kRDF_InstanceOf ||
00939                  aArc == kRDF_type)
00940         {
00941             *result = PR_TRUE;
00942         }
00943     }
00944     return NS_OK;
00945 }
00946 
00947 
00948 
00949 NS_IMETHODIMP
00950 FileSystemDataSource::ArcLabelsIn(nsIRDFNode *node,
00951                             nsISimpleEnumerator ** labels /* out */)
00952 {
00953 //  NS_NOTYETIMPLEMENTED("write me");
00954     return NS_ERROR_NOT_IMPLEMENTED;
00955 }
00956 
00957 
00958 
00959 NS_IMETHODIMP
00960 FileSystemDataSource::ArcLabelsOut(nsIRDFResource *source,
00961                    nsISimpleEnumerator **labels /* out */)
00962 {
00963     NS_PRECONDITION(source != nsnull, "null ptr");
00964     if (! source)
00965     return NS_ERROR_NULL_POINTER;
00966 
00967     NS_PRECONDITION(labels != nsnull, "null ptr");
00968     if (! labels)
00969     return NS_ERROR_NULL_POINTER;
00970 
00971     nsresult rv;
00972 
00973     if (source == kNC_FileSystemRoot)
00974     {
00975         nsCOMPtr<nsISupportsArray> array;
00976         rv = NS_NewISupportsArray(getter_AddRefs(array));
00977         if (NS_FAILED(rv)) return rv;
00978 
00979         array->AppendElement(kNC_Child);
00980         array->AppendElement(kNC_pulse);
00981 
00982         nsISimpleEnumerator* result = new nsArrayEnumerator(array);
00983         if (! result)
00984             return NS_ERROR_OUT_OF_MEMORY;
00985 
00986         NS_ADDREF(result);
00987         *labels = result;
00988         return NS_OK;
00989     }
00990     else if (isFileURI(source))
00991     {
00992         nsCOMPtr<nsISupportsArray> array;
00993         rv = NS_NewISupportsArray(getter_AddRefs(array));
00994         if (NS_FAILED(rv)) return rv;
00995 
00996         if (isDirURI(source))
00997         {
00998 #ifdef  XP_WIN
00999             if (isValidFolder(source) == PR_TRUE)
01000             {
01001                 array->AppendElement(kNC_Child);
01002             }
01003 #else
01004             array->AppendElement(kNC_Child);
01005 #endif
01006             array->AppendElement(kNC_pulse);
01007         }
01008 
01009         nsISimpleEnumerator* result = new nsArrayEnumerator(array);
01010         if (! result)
01011             return NS_ERROR_OUT_OF_MEMORY;
01012 
01013         NS_ADDREF(result);
01014         *labels = result;
01015         return NS_OK;
01016     }
01017 
01018     return NS_NewEmptyEnumerator(labels);
01019 }
01020 
01021 
01022 
01023 NS_IMETHODIMP
01024 FileSystemDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
01025 {
01026     NS_NOTYETIMPLEMENTED("sorry!");
01027     return NS_ERROR_NOT_IMPLEMENTED;
01028 }
01029 
01030 
01031 
01032 NS_IMETHODIMP
01033 FileSystemDataSource::AddObserver(nsIRDFObserver *n)
01034 {
01035     NS_PRECONDITION(n != nsnull, "null ptr");
01036     if (! n)
01037         return NS_ERROR_NULL_POINTER;
01038 
01039     if (! mObservers)
01040     {
01041         nsresult rv;
01042         rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
01043         if (NS_FAILED(rv)) return rv;
01044     }
01045     mObservers->AppendElement(n);
01046     return NS_OK;
01047 }
01048 
01049 
01050 
01051 NS_IMETHODIMP
01052 FileSystemDataSource::RemoveObserver(nsIRDFObserver *n)
01053 {
01054     NS_PRECONDITION(n != nsnull, "null ptr");
01055     if (! n)
01056         return NS_ERROR_NULL_POINTER;
01057 
01058     if (! mObservers)
01059         return NS_OK;
01060 
01061     mObservers->RemoveElement(n);
01062     return NS_OK;
01063 }
01064 
01065 
01066 
01067 NS_IMETHODIMP
01068 FileSystemDataSource::GetAllCmds(nsIRDFResource* source,
01069                                      nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
01070 {
01071     return(NS_NewEmptyEnumerator(commands));
01072 }
01073 
01074 
01075 
01076 NS_IMETHODIMP
01077 FileSystemDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
01078                                        nsIRDFResource*   aCommand,
01079                                        nsISupportsArray/*<nsIRDFResource>*/* aArguments,
01080                                        PRBool* aResult)
01081 {
01082     return(NS_ERROR_NOT_IMPLEMENTED);
01083 }
01084 
01085 
01086 
01087 NS_IMETHODIMP
01088 FileSystemDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
01089                                 nsIRDFResource*   aCommand,
01090                                 nsISupportsArray/*<nsIRDFResource>*/* aArguments)
01091 {
01092     return(NS_ERROR_NOT_IMPLEMENTED);
01093 }
01094 
01095 
01096 
01097 NS_IMETHODIMP
01098 FileSystemDataSource::BeginUpdateBatch()
01099 {
01100     return NS_OK;
01101 }
01102 
01103 
01104 
01105 NS_IMETHODIMP
01106 FileSystemDataSource::EndUpdateBatch()
01107 {
01108     return NS_OK;
01109 }
01110 
01111 
01112 
01113 nsresult
01114 NS_NewRDFFileSystemDataSource(nsIRDFDataSource **result)
01115 {
01116     if (!result)
01117         return NS_ERROR_NULL_POINTER;
01118 
01119     // only one file system data source
01120     if (nsnull == gFileSystemDataSource)
01121     {
01122         if ((gFileSystemDataSource = new FileSystemDataSource()) == nsnull)
01123         {
01124             return NS_ERROR_OUT_OF_MEMORY;
01125         }
01126     }
01127     NS_ADDREF(gFileSystemDataSource);
01128     *result = gFileSystemDataSource;
01129     return NS_OK;
01130 }
01131 
01132 
01133 
01134 nsresult
01135 FileSystemDataSource::GetVolumeList(nsISimpleEnumerator** aResult)
01136 {
01137     nsresult rv;
01138     nsCOMPtr<nsISupportsArray> volumes;
01139 
01140     rv = NS_NewISupportsArray(getter_AddRefs(volumes));
01141     if (NS_FAILED(rv)) return rv;
01142 
01143     nsCOMPtr<nsIRDFResource> vol;
01144 
01145 #ifdef  XP_MAC
01146     StrFileName     fname;
01147     HParamBlockRec  pb;
01148     for (int16 volNum = 1; ; volNum++)
01149     {
01150         pb.volumeParam.ioCompletion = NULL;
01151         pb.volumeParam.ioVolIndex = volNum;
01152         pb.volumeParam.ioNamePtr = (StringPtr)fname;
01153         if (PBHGetVInfo(&pb,FALSE) != noErr)
01154             break;
01155         FSSpec fss(pb.volumeParam.ioVRefNum, fsRtParID, fname);
01156         nsCOMPtr<nsILocalFileMac> lf;
01157         NS_NewLocalFileWithFSSpec(fss, true, getter_AddRefs(lf));
01158 
01159         nsCOMPtr<nsIURI> furi;
01160         NS_NewFileURI(getter_AddRefs(furi), lf); 
01161 
01162         nsXPIDLCString spec;
01163         furi->GetSpec(getter_Copies(spec);
01164 
01165         rv = gRDFService->GetResource(spec, getter_AddRefs(vol));
01166         if (NS_FAILED(rv)) return rv;
01167 
01168         volumes->AppendElement(vol);
01169     }
01170 #endif
01171 
01172 #if defined (XP_WIN) && !defined (WINCE)
01173 
01174     PRInt32         driveType;
01175     char            drive[32];
01176     PRInt32         volNum;
01177     char            *url;
01178 
01179     for (volNum = 0; volNum < 26; volNum++)
01180     {
01181         sprintf(drive, "%c:\\", volNum + 'A');
01182         driveType = GetDriveType(drive);
01183         if (driveType != DRIVE_UNKNOWN && driveType != DRIVE_NO_ROOT_DIR)
01184         {
01185             if (nsnull != (url = PR_smprintf("file:///%c|/", volNum + 'A')))
01186             {
01187                 rv = gRDFService->GetResource(nsDependentCString(url),
01188                                               getter_AddRefs(vol));
01189                 PR_Free(url);
01190 
01191                 if (NS_FAILED(rv)) return rv;
01192                 volumes->AppendElement(vol);
01193             }
01194         }
01195     }
01196 #endif
01197 
01198 #if defined(XP_UNIX) || defined(XP_BEOS)
01199     gRDFService->GetResource(NS_LITERAL_CSTRING("file:///"), getter_AddRefs(vol));
01200     volumes->AppendElement(vol);
01201 #endif
01202 
01203 #ifdef XP_OS2
01204     ULONG ulDriveNo = 0;
01205     ULONG ulDriveMap = 0;
01206     char *url;
01207 
01208     rv = DosQueryCurrentDisk(&ulDriveNo, &ulDriveMap);
01209     if (NS_FAILED(rv))
01210         return rv;
01211 
01212     for (int volNum = 0; volNum < 26; volNum++)
01213     {
01214         if (((ulDriveMap << (31 - volNum)) >> 31))
01215         {
01216             if (nsnull != (url = PR_smprintf("file:///%c|/", volNum + 'A')))
01217             {
01218                 rv = gRDFService->GetResource(nsDependentCString(url), getter_AddRefs(vol));
01219                 PR_Free(url);
01220 
01221                 if (NS_FAILED(rv)) return rv;
01222                 volumes->AppendElement(vol);
01223             }
01224         }
01225 
01226     }
01227 #endif
01228 
01229     nsISimpleEnumerator* result = new nsArrayEnumerator(volumes);
01230     if (! result)
01231         return NS_ERROR_OUT_OF_MEMORY;
01232 
01233     NS_ADDREF(result);
01234     *aResult = result;
01235 
01236     return NS_OK;
01237 }
01238 
01239 
01240 
01241 #ifdef  XP_WIN
01242 PRBool
01243 FileSystemDataSource::isValidFolder(nsIRDFResource *source)
01244 {
01245     PRBool  isValid = PR_TRUE;
01246     if (!ieFavoritesDir)    return(isValid);
01247 
01248     nsresult        rv;
01249     nsCString       uri;
01250     rv = source->GetValueUTF8(uri);
01251     if (NS_FAILED(rv)) return(isValid);
01252 
01253     NS_ConvertUTF8toUTF16 theURI(uri);
01254     if (theURI.Find(ieFavoritesDir) == 0)
01255     {
01256         isValid = PR_FALSE;
01257 
01258         nsCOMPtr<nsISimpleEnumerator>   folderEnum;
01259         if (NS_SUCCEEDED(rv = GetFolderList(source, PR_TRUE, PR_FALSE, getter_AddRefs(folderEnum))))
01260         {
01261             PRBool      hasAny = PR_FALSE, hasMore;
01262             while (NS_SUCCEEDED(folderEnum->HasMoreElements(&hasMore)) &&
01263                     (hasMore == PR_TRUE))
01264             {
01265                 hasAny = PR_TRUE;
01266 
01267                 nsCOMPtr<nsISupports>       isupports;
01268                 if (NS_FAILED(rv = folderEnum->GetNext(getter_AddRefs(isupports))))
01269                     break;
01270                 nsCOMPtr<nsIRDFResource>    res = do_QueryInterface(isupports);
01271                 if (!res)   break;
01272 
01273                 nsCOMPtr<nsIRDFLiteral>     nameLiteral;
01274                 if (NS_FAILED(rv = GetName(res, getter_AddRefs(nameLiteral))))
01275                     break;
01276                 
01277                 const PRUnichar         *uniName;
01278                 if (NS_FAILED(rv = nameLiteral->GetValueConst(&uniName)))
01279                     break;
01280                 nsAutoString            name(uniName);
01281 
01282                 // An empty folder, or a folder that contains just "desktop.ini",
01283                 // is considered to be a IE Favorite; otherwise, its a folder
01284                 if (!name.LowerCaseEqualsLiteral("desktop.ini"))
01285                 {
01286                     isValid = PR_TRUE;
01287                     break;
01288                 }
01289             }
01290             if (hasAny == PR_FALSE) isValid = PR_TRUE;
01291         }
01292     }
01293     return(isValid);
01294 }
01295 #endif
01296 
01297 
01298 
01299 nsresult
01300 FileSystemDataSource::GetFolderList(nsIRDFResource *source, PRBool allowHidden,
01301                 PRBool onlyFirst, nsISimpleEnumerator** aResult)
01302 {
01303     if (!isDirURI(source))
01304         return(NS_RDF_NO_VALUE);
01305 
01306     nsresult                    rv;
01307     nsCOMPtr<nsISupportsArray>  nameArray;
01308 
01309     rv = NS_NewISupportsArray(getter_AddRefs(nameArray));
01310     if (NS_FAILED(rv))
01311         return(rv);
01312 
01313     const char      *parentURI = nsnull;
01314     rv = source->GetValueConst(&parentURI);
01315     if (NS_FAILED(rv))
01316         return(rv);
01317     if (!parentURI)
01318         return(NS_ERROR_UNEXPECTED);
01319 
01320     nsCOMPtr<nsIURI>    aIURI;
01321     if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(parentURI))))
01322         return(rv);
01323 
01324     nsCOMPtr<nsIFileURL>    fileURL = do_QueryInterface(aIURI);
01325     if (!fileURL)
01326         return(PR_FALSE);
01327 
01328     nsCOMPtr<nsIFile>   aDir;
01329     if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aDir))))
01330         return(rv);
01331 
01332     // ensure that we DO NOT resolve aliases
01333     nsCOMPtr<nsILocalFile>  aDirLocal = do_QueryInterface(aDir);
01334     if (aDirLocal)
01335         aDirLocal->SetFollowLinks(PR_FALSE);
01336 
01337     nsCOMPtr<nsISimpleEnumerator>   dirContents;
01338     if (NS_FAILED(rv = aDir->GetDirectoryEntries(getter_AddRefs(dirContents))))
01339         return(rv);
01340     if (!dirContents)
01341         return(NS_ERROR_UNEXPECTED);
01342 
01343     PRBool          hasMore;
01344     while(NS_SUCCEEDED(rv = dirContents->HasMoreElements(&hasMore)) &&
01345         (hasMore == PR_TRUE))
01346     {
01347         nsCOMPtr<nsISupports>   isupports;
01348         if (NS_FAILED(rv = dirContents->GetNext(getter_AddRefs(isupports))))
01349             break;
01350 
01351         nsCOMPtr<nsIFile>   aFile = do_QueryInterface(isupports);
01352         if (!aFile)
01353             break;
01354 
01355         if (allowHidden == PR_FALSE)
01356         {
01357             PRBool          hiddenFlag = PR_FALSE;
01358             if (NS_FAILED(rv = aFile->IsHidden(&hiddenFlag)))
01359                 break;
01360             if (hiddenFlag == PR_TRUE)
01361                 continue;
01362         }
01363 
01364         nsAutoString leafStr;
01365         if (NS_FAILED(rv = aFile->GetLeafName(leafStr)))
01366             break;
01367         if (leafStr.IsEmpty())
01368             continue;
01369   
01370         nsCAutoString           fullURI;
01371         fullURI.Assign(parentURI);
01372         if (fullURI.Last() != '/')
01373         {
01374             fullURI.Append('/');
01375         }
01376 
01377         char    *escLeafStr = nsEscape(NS_ConvertUCS2toUTF8(leafStr).get(), url_Path);
01378         leafStr.Truncate();
01379 
01380         if (!escLeafStr)
01381             continue;
01382   
01383         nsCAutoString           leaf(escLeafStr);
01384         Recycle(escLeafStr);
01385         escLeafStr = nsnull;
01386 
01387         // using nsEscape() [above] doesn't escape slashes, so do that by hand
01388         PRInt32         aOffset;
01389         while ((aOffset = leaf.FindChar('/')) >= 0)
01390         {
01391             leaf.Cut((PRUint32)aOffset, 1);
01392             leaf.Insert("%2F", (PRUint32)aOffset);
01393         }
01394 
01395         // append the encoded name
01396         fullURI.Append(leaf);
01397 
01398         PRBool          dirFlag = PR_FALSE;
01399         rv = aFile->IsDirectory(&dirFlag);
01400         if (NS_SUCCEEDED(rv) && (dirFlag == PR_TRUE))
01401         {
01402             fullURI.Append('/');
01403         }
01404 
01405         nsCOMPtr<nsIRDFResource>    fileRes;
01406         gRDFService->GetResource(fullURI, getter_AddRefs(fileRes));
01407 
01408         nameArray->AppendElement(fileRes);
01409 
01410         if (onlyFirst == PR_TRUE)
01411             break;
01412     }
01413 
01414     nsISimpleEnumerator* result = new nsArrayEnumerator(nameArray);
01415     if (! result)
01416         return NS_ERROR_OUT_OF_MEMORY;
01417 
01418     NS_ADDREF(result);
01419     *aResult = result;
01420 
01421     return NS_OK;
01422 }
01423 
01424 
01425 
01426 nsresult
01427 FileSystemDataSource::GetLastMod(nsIRDFResource *source, nsIRDFDate **aResult)
01428 {
01429     *aResult = nsnull;
01430 
01431     nsresult        rv;
01432     const char      *uri = nsnull;
01433 
01434     rv = source->GetValueConst(&uri);
01435     if (NS_FAILED(rv)) return(rv);
01436     if (!uri)
01437         return(NS_ERROR_UNEXPECTED);
01438 
01439     nsCOMPtr<nsIURI>    aIURI;
01440     if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
01441         return(rv);
01442 
01443     nsCOMPtr<nsIFileURL>    fileURL = do_QueryInterface(aIURI);
01444     if (!fileURL)
01445         return(PR_FALSE);
01446 
01447     nsCOMPtr<nsIFile>   aFile;
01448     if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
01449         return(rv);
01450     if (!aFile)
01451         return(NS_ERROR_UNEXPECTED);
01452 
01453     // ensure that we DO NOT resolve aliases
01454     nsCOMPtr<nsILocalFile>  aFileLocal = do_QueryInterface(aFile);
01455     if (aFileLocal)
01456         aFileLocal->SetFollowLinks(PR_FALSE);
01457 
01458     PRInt64 lastModDate;
01459     if (NS_FAILED(rv = aFile->GetLastModifiedTime(&lastModDate)))
01460         return(rv);
01461 
01462     // convert from milliseconds to seconds
01463     PRTime      temp64, thousand;
01464     LL_I2L(thousand, PR_MSEC_PER_SEC);
01465     LL_MUL(temp64, lastModDate, thousand);
01466 
01467     gRDFService->GetDateLiteral(temp64, aResult);
01468 
01469     return(NS_OK);
01470 }
01471 
01472 
01473 
01474 nsresult
01475 FileSystemDataSource::GetFileSize(nsIRDFResource *source, nsIRDFInt **aResult)
01476 {
01477     *aResult = nsnull;
01478 
01479     nsresult        rv;
01480     const char      *uri = nsnull;
01481 
01482     rv = source->GetValueConst(&uri);
01483     if (NS_FAILED(rv))
01484         return(rv);
01485     if (!uri)
01486         return(NS_ERROR_UNEXPECTED);
01487 
01488     nsCOMPtr<nsIURI>    aIURI;
01489     if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
01490         return(rv);
01491 
01492     nsCOMPtr<nsIFileURL>    fileURL = do_QueryInterface(aIURI);
01493     if (!fileURL)
01494         return(PR_FALSE);
01495 
01496     nsCOMPtr<nsIFile>   aFile;
01497     if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
01498         return(rv);
01499     if (!aFile)
01500         return(NS_ERROR_UNEXPECTED);
01501 
01502     // ensure that we DO NOT resolve aliases
01503     nsCOMPtr<nsILocalFile>  aFileLocal = do_QueryInterface(aFile);
01504     if (aFileLocal)
01505         aFileLocal->SetFollowLinks(PR_FALSE);
01506 
01507     // don't do anything with directories
01508     PRBool  isDir = PR_FALSE;
01509     if (NS_FAILED(rv = aFile->IsDirectory(&isDir)))
01510         return(rv);
01511     if (isDir == PR_TRUE)
01512         return(NS_RDF_NO_VALUE);
01513 
01514     PRInt64     aFileSize64;
01515 #ifdef  XP_MAC
01516     // on Mac, get total file size (data + resource fork)
01517     nsCOMPtr<nsILocalFileMac>   aMacFile = do_QueryInterface(aFile);
01518     if (!aMacFile)
01519         return(NS_ERROR_UNEXPECTED);
01520     if (NS_FAILED(rv = aMacFile->GetFileSizeWithResFork(&aFileSize64)))
01521         return(rv);
01522 #else
01523     if (NS_FAILED(rv = aFile->GetFileSize(&aFileSize64)))
01524         return(rv);
01525 #endif
01526 
01527     // convert 64bits to 32bits
01528     PRInt32     aFileSize32 = 0;
01529     LL_L2I(aFileSize32, aFileSize64);
01530 
01531     gRDFService->GetIntLiteral(aFileSize32, aResult);
01532 
01533     return(NS_OK);
01534 }
01535 
01536 
01537 
01538 nsresult
01539 FileSystemDataSource::GetName(nsIRDFResource *source, nsIRDFLiteral **aResult)
01540 {
01541     nsresult        rv;
01542     const char      *uri = nsnull;
01543 
01544     rv = source->GetValueConst(&uri);
01545     if (NS_FAILED(rv))
01546         return(rv);
01547     if (!uri)
01548         return(NS_ERROR_UNEXPECTED);
01549 
01550     nsCOMPtr<nsIURI>    aIURI;
01551     if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(uri))))
01552         return(rv);
01553 
01554     nsCOMPtr<nsIFileURL>    fileURL = do_QueryInterface(aIURI);
01555     if (!fileURL)
01556         return(PR_FALSE);
01557 
01558     nsCOMPtr<nsIFile>   aFile;
01559     if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aFile))))
01560         return(rv);
01561     if (!aFile)
01562         return(NS_ERROR_UNEXPECTED);
01563 
01564     // ensure that we DO NOT resolve aliases
01565     nsCOMPtr<nsILocalFile>  aFileLocal = do_QueryInterface(aFile);
01566     if (aFileLocal)
01567         aFileLocal->SetFollowLinks(PR_FALSE);
01568 
01569     nsAutoString name;
01570     if (NS_FAILED(rv = aFile->GetLeafName(name)))
01571         return(rv);
01572     if (name.IsEmpty())
01573         return(NS_ERROR_UNEXPECTED);
01574 
01575 #ifdef  XP_MAC
01576     nsCOMPtr<nsILocalFileMac>   aMacFile = do_QueryInterface(aFile);
01577     if (aMacFile)
01578     {
01579         PRBool isPackageFlag = PR_FALSE;
01580         rv = aMacFile->IsPackage(&isPackageFlag);
01581         if (NS_SUCCEEDED(rv) && (isPackageFlag == PR_TRUE))
01582         {
01583             // mungle package names under Mac OS 9/X
01584             PRUint32 len = name.Length();
01585             if (name.RFind(".app", PR_TRUE) == len - 4)
01586             {
01587                 name.SetLength(len-4);
01588             }
01589         }
01590     }
01591 #endif
01592 
01593 #ifdef  XP_WIN
01594     // special hack for IE favorites under Windows; strip off the
01595     // trailing ".url" or ".lnk" at the end of IE favorites names
01596     PRInt32 nameLen = name.Length();
01597     if ((strncmp(uri, ieFavoritesDir, strlen(ieFavoritesDir)) == 0) && (nameLen > 4))
01598     {
01599         nsAutoString extension;
01600         name.Right(extension, 4);
01601         if (extension.LowerCaseEqualsLiteral(".url") ||
01602             extension.LowerCaseEqualsLiteral(".lnk"))
01603         {
01604             name.Truncate(nameLen - 4);
01605         }
01606     }
01607 #endif
01608 
01609 #ifdef  XP_BEOS
01610     // under BEOS, try and get the "META:title" attribute (if its a file)
01611     if (strstr(uri, netPositiveDir) != 0)
01612     {
01613         PRBool value;
01614         if ((NS_SUCCEEDED(aFileLocal->IsFile(&value) && value)) ||
01615             (NS_SUCCEEDED(aFileLocal->IsDirectory(&value) && value)))
01616         {
01617             nsXPIDLCString nativePath;
01618             aFileLocal->GetNativePath(nativePath);
01619 
01620             rv = NS_ERROR_FAILURE;
01621             if (nativePath) 
01622             {
01623                 BFile   bf(nativePath.get(), B_READ_ONLY);
01624                 if (bf.InitCheck() == B_OK)
01625                 {
01626                     char        beNameAttr[4096];
01627                     ssize_t     len;
01628 
01629                     if ((len = bf.ReadAttr("META:title", B_STRING_TYPE,
01630                         0, beNameAttr, sizeof(beNameAttr)-1)) > 0)
01631                     {
01632                         beNameAttr[len] = '\0';
01633                         CopyUTF8toUTF16(beNameAttr, name);
01634                         rv = NS_OK;
01635                     }
01636                 }
01637             }
01638             if (NS_OK != rv)
01639             {
01640                 nsCAutoString leafName;
01641                 rv = aFileLocal->GetNativeLeafName(leafName);
01642                 if (NS_SUCCEEDED(rv)) {
01643                     CopyUTF8toUTF16(leafName, name);
01644                     rv = NS_OK;
01645                 }
01646             }
01647         }
01648     }
01649 #endif
01650 
01651     gRDFService->GetLiteral(name.get(), aResult);
01652 
01653     return NS_OK;
01654 }
01655 
01656 
01657 
01658 #ifdef USE_NC_EXTENSION
01659 nsresult
01660 FileSystemDataSource::GetExtension(nsIRDFResource *source, nsIRDFLiteral **aResult)
01661 {
01662     nsCOMPtr<nsIRDFLiteral> name;
01663     nsresult rv = GetName(source, getter_AddRefs(name));
01664     if (NS_FAILED(rv))
01665         return rv;
01666 
01667     const PRUnichar* unicodeLeafName;
01668     rv = name->GetValueConst(&unicodeLeafName);
01669     if (NS_FAILED(rv))
01670         return rv;
01671 
01672     nsAutoString filename(unicodeLeafName);
01673     PRInt32 lastDot = filename.RFindChar('.');
01674     if (lastDot == -1)
01675     {
01676         gRDFService->GetLiteral(EmptyString().get(), aResult);
01677     }
01678     else
01679     {
01680         nsAutoString extension;
01681         filename.Right(extension, (filename.Length() - lastDot));
01682         gRDFService->GetLiteral(extension.get(), aResult);
01683     }
01684 
01685     return NS_OK;
01686 }
01687 #endif
01688 
01689 #ifdef  XP_WIN
01690 nsresult
01691 FileSystemDataSource::getIEFavoriteURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral)
01692 {
01693     nsresult        rv = NS_OK;
01694     
01695     *urlLiteral = nsnull;
01696 
01697     nsCOMPtr<nsIFile> f;
01698     NS_GetFileFromURLSpec(NS_ConvertUCS2toUTF8(aFileURL), getter_AddRefs(f)); 
01699 
01700     PRBool value;
01701 
01702     if (NS_SUCCEEDED(f->IsDirectory(&value)) && value)
01703     {
01704         if (isValidFolder(source))
01705             return(NS_RDF_NO_VALUE);
01706         aFileURL.AppendLiteral("desktop.ini");
01707     }
01708     else if (aFileURL.Length() > 4)
01709     {
01710         nsAutoString    extension;
01711 
01712         aFileURL.Right(extension, 4);
01713         if (!extension.LowerCaseEqualsLiteral(".url"))
01714         {
01715             return(NS_RDF_NO_VALUE);
01716         }
01717     }
01718 
01719     nsCOMPtr<nsIInputStream> strm;
01720     NS_NewLocalFileInputStream(getter_AddRefs(strm),f);
01721     nsCOMPtr<nsILineInputStream> linereader = do_QueryInterface(strm, &rv);
01722 
01723     nsAutoString    line;
01724     nsCAutoString   cLine;
01725     while(NS_SUCCEEDED(rv))
01726     {
01727         PRBool  isEOF;
01728         rv = linereader->ReadLine(cLine, &isEOF);
01729         CopyASCIItoUTF16(cLine, line);
01730 
01731         if (isEOF)
01732         {
01733             if (line.Find("URL=", PR_TRUE) == 0)
01734             {
01735                 line.Cut(0, 4);
01736                 rv = gRDFService->GetLiteral(line.get(), urlLiteral);
01737                 break;
01738             }
01739             else if (line.Find("CDFURL=", PR_TRUE) == 0)
01740             {
01741                 line.Cut(0, 7);
01742                 rv = gRDFService->GetLiteral(line.get(), urlLiteral);
01743                 break;
01744             }
01745             line.Truncate();
01746         }
01747     }
01748 
01749     return(rv);
01750 }
01751 #endif
01752 
01753 
01754 
01755 nsresult
01756 FileSystemDataSource::GetURL(nsIRDFResource *source, PRBool *isFavorite, nsIRDFLiteral** aResult)
01757 {
01758     if (isFavorite) *isFavorite = PR_FALSE;
01759 
01760     nsresult        rv;
01761     nsCString       uri;
01762        
01763     rv = source->GetValueUTF8(uri);
01764     if (NS_FAILED(rv))
01765         return(rv);
01766 
01767     NS_ConvertUTF8toUTF16 url(uri);
01768 
01769 #ifdef  XP_WIN
01770     // under Windows, if its an IE favorite, munge the URL
01771     if (ieFavoritesDir)
01772     {
01773         if (url.Find(ieFavoritesDir) == 0)
01774         {
01775             if (isFavorite) *isFavorite = PR_TRUE;
01776             rv = getIEFavoriteURL(source, url, aResult);
01777             return(rv);
01778         }
01779     }
01780 #endif
01781 
01782 #ifdef  XP_BEOS
01783     // under BEOS, try and get the "META:url" attribute
01784     if (netPositiveDir)
01785     {
01786         if (strstr(uri.get(), netPositiveDir) != 0)
01787         {
01788             if (isFavorite) *isFavorite = PR_TRUE;
01789             rv = getNetPositiveURL(source, url, aResult);
01790             return(rv);
01791         }
01792     }
01793 #endif
01794 
01795     // if we fall through to here, its not any type of bookmark
01796     // stored in the platform native file system, so just set the URL
01797 
01798     gRDFService->GetLiteral(url.get(), aResult);
01799 
01800     return(NS_OK);
01801 }
01802 
01803 
01804 
01805 #ifdef  XP_BEOS
01806 
01807 nsresult
01808 FileSystemDataSource::getNetPositiveURL(nsIRDFResource *source, nsString aFileURL, nsIRDFLiteral **urlLiteral)
01809 {
01810     nsresult        rv = NS_RDF_NO_VALUE;
01811 
01812     *urlLiteral = nsnull;
01813 
01814 
01815     nsCOMPtr<nsIFile> f;
01816     NS_GetFileFromURLSpec(NS_ConvertUCS2toUTF8(aFileURL), getter_AddRefs(f)); 
01817 
01818 
01819 
01820     nsXPIDLCString nativePath;
01821     f->GetNativePath(nativePath);
01822 
01823     PRBool value;
01824     if (NS_SUCCEEDED(f->IsFile(&value) && value))
01825     {
01826         if (nativePath)
01827         {
01828             BFile   bf(nativePath.get(), B_READ_ONLY);
01829             if (bf.InitCheck() == B_OK)
01830             {
01831                 char        beURLattr[4096];
01832                 ssize_t     len;
01833 
01834                 if ((len = bf.ReadAttr("META:url", B_STRING_TYPE,
01835                     0, beURLattr, sizeof(beURLattr)-1)) > 0)
01836                 {
01837                     beURLattr[len] = '\0';
01838                     nsAutoString    bookmarkURL;
01839                     CopyUTF8toUTF16(beURLattr, bookmarkURL);
01840                     rv = gRDFService->GetLiteral(bookmarkURL.get(),
01841                         urlLiteral);
01842                 }
01843             }
01844         }
01845     }
01846     return(rv);
01847 }
01848 
01849 #endif