Index: xpcom/io/SpecialSystemDirectory.cpp =================================================================== RCS file: /cvsroot/mozilla/xpcom/io/SpecialSystemDirectory.cpp,v retrieving revision 1.32 diff -p -u -B -U 10 -r1.32 SpecialSystemDirectory.cpp --- xpcom/io/SpecialSystemDirectory.cpp 6 Sep 2007 21:44:05 -0000 1.32 +++ xpcom/io/SpecialSystemDirectory.cpp 10 Oct 2007 20:19:17 -0000 @@ -231,20 +231,230 @@ GetUnixHomeDir(nsILocalFile** aFile) } else { return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)), PR_TRUE, aFile); } #else return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), PR_TRUE, aFile); #endif } + +/* + The following licence applies to the xdg_user_dir_lookup_with_fallback + function: + + Copyright (c) 2007 Red Hat, inc + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +static char * +xdg_user_dir_lookup (const char *type) +{ + FILE *file; + char *home_dir, *config_home, *config_file; + char buffer[512]; + char *user_dir; + char *p, *d; + int len; + int relative; + + home_dir = getenv ("HOME"); + + if (home_dir == NULL) + goto error; + + config_home = getenv ("XDG_CONFIG_HOME"); + if (config_home == NULL || config_home[0] == 0) + { + config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1); + if (config_file == NULL) + goto error; + + strcpy (config_file, home_dir); + strcat (config_file, "/.config/user-dirs.dirs"); + } + else + { + config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1); + if (config_file == NULL) + goto error; + + strcpy (config_file, config_home); + strcat (config_file, "/user-dirs.dirs"); + } + + file = fopen (config_file, "r"); + free (config_file); + if (file == NULL) + goto error; + + user_dir = NULL; + while (fgets (buffer, sizeof (buffer), file)) + { + /* Remove newline at end */ + len = strlen (buffer); + if (len > 0 && buffer[len-1] == '\n') + buffer[len-1] = 0; + + p = buffer; + while (*p == ' ' || *p == '\t') + p++; + + if (strncmp (p, "XDG_", 4) != 0) + continue; + p += 4; + if (strncmp (p, type, strlen (type)) != 0) + continue; + p += strlen (type); + if (strncmp (p, "_DIR", 4) != 0) + continue; + p += 4; + + while (*p == ' ' || *p == '\t') + p++; + + if (*p != '=') + continue; + p++; + + while (*p == ' ' || *p == '\t') + p++; + + if (*p != '"') + continue; + p++; + + relative = 0; + if (strncmp (p, "$HOME/", 6) == 0) + { + p += 6; + relative = 1; + } + else if (*p != '/') + continue; + + if (relative) + { + user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1); + if (user_dir == NULL) + goto error2; + + strcpy (user_dir, home_dir); + strcat (user_dir, "/"); + } + else + { + user_dir = (char*) malloc (strlen (p) + 1); + if (user_dir == NULL) + goto error2; + + *user_dir = 0; + } + + d = user_dir + strlen (user_dir); + while (*p && *p != '"') + { + if ((*p == '\\') && (*(p+1) != 0)) + p++; + *d++ = *p++; + } + *d = 0; + } +error2: + fclose (file); + + if (user_dir) + return user_dir; + + error: + return NULL; +} + +static const char xdg_user_dirs[] = + "DESKTOP\0" + "DOCUMENTS\0" + "DOWNLOAD\0" + "MUSIC\0" + "PICTURES\0" + "PUBLICSHARE\0" + "TEMPLATES\0" + "VIDEOS"; + +static const PRUint8 xdg_user_dir_offsets[] = { + 0, + 8, + 18, + 27, + 33, + 42, + 54, + 64 +}; + +static nsresult +GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory, + nsILocalFile** aFile) +{ + nsresult rv; + PRBool exists; + char *dir = xdg_user_dir_lookup + (xdg_user_dirs + xdg_user_dir_offsets[aSystemDirectory - + Unix_XDG_Desktop]); + if (dir) { + rv = NS_NewNativeLocalFile(nsDependentCString(dir), PR_TRUE, aFile); + free(dir); + if (NS_SUCCEEDED(rv)) { + rv = (*aFile)->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) + return rv; + } + } + + rv = GetUnixHomeDir(aFile); + if (NS_FAILED(rv)) + return rv; + + // for the XDG desktop dir, fall back to HOME/Desktop; otherwise to HOME + if (aSystemDirectory != Unix_XDG_Desktop) + return NS_OK; + + rv = (*aFile)->AppendNative(NS_LITERAL_CSTRING("Desktop")); + if (NS_FAILED(rv)) + return rv; + + rv = (*aFile)->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) + return rv; + + // last-ditch fallback to HOME + return GetUnixHomeDir(aFile); +} #endif nsresult GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory, nsILocalFile** aFile) { #if defined(XP_WIN) WCHAR path[MAX_PATH]; #else char path[MAXPATHLEN]; @@ -568,39 +778,29 @@ GetSpecialSystemDirectory(SystemDirector PR_TRUE, aFile); case Unix_LibDirectory: return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"), PR_TRUE, aFile); case Unix_HomeDirectory: return GetUnixHomeDir(aFile); - case Unix_DesktopDirectory: - { - nsCOMPtr home; - nsresult rv = GetUnixHomeDir(getter_AddRefs(home)); - if (NS_FAILED(rv)) - return rv; - rv = home->AppendNative(NS_LITERAL_CSTRING("Desktop")); - if (NS_FAILED(rv)) - return rv; - PRBool exists; - rv = home->Exists(&exists); - if (NS_FAILED(rv)) - return rv; - if (!exists) - return GetUnixHomeDir(aFile); - - NS_ADDREF(*aFile = home); - return NS_OK; - } + case Unix_XDG_Desktop: + case Unix_XDG_Documents: + case Unix_XDG_Download: + case Unix_XDG_Music: + case Unix_XDG_Pictures: + case Unix_XDG_PublicShare: + case Unix_XDG_Templates: + case Unix_XDG_Videos: + return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile); #endif #ifdef XP_BEOS case BeOS_SettingsDirectory: { return GetBeOSFolder(B_USER_SETTINGS_DIRECTORY,0, aFile); } case BeOS_HomeDirectory: { Index: xpcom/io/SpecialSystemDirectory.h =================================================================== RCS file: /cvsroot/mozilla/xpcom/io/SpecialSystemDirectory.h,v retrieving revision 1.9 diff -p -u -B -U 10 -r1.9 SpecialSystemDirectory.h --- xpcom/io/SpecialSystemDirectory.h 16 Nov 2006 09:10:08 -0000 1.9 +++ xpcom/io/SpecialSystemDirectory.h 10 Oct 2007 20:19:17 -0000 @@ -107,22 +107,29 @@ enum SystemDirectories { Win_Appdata = 225, Win_Printhood = 226, Win_Cookies = 227, Win_LocalAppdata = 228, Win_ProgramFiles = 229, Win_Downloads = 230, Unix_LocalDirectory = 301, Unix_LibDirectory = 302, Unix_HomeDirectory = 303, - Unix_DesktopDirectory = 304, - + Unix_XDG_Desktop = 304, + Unix_XDG_Documents = 305, + Unix_XDG_Download = 306, + Unix_XDG_Music = 307, + Unix_XDG_Pictures = 308, + Unix_XDG_PublicShare = 309, + Unix_XDG_Templates = 310, + Unix_XDG_Videos = 311, + BeOS_SettingsDirectory = 401, BeOS_HomeDirectory = 402, BeOS_DesktopDirectory = 403, BeOS_SystemDirectory = 404, OS2_SystemDirectory = 501, OS2_OS2Directory = 502, OS2_DesktopDirectory = 503, OS2_HomeDirectory = 504 }; Index: xpcom/io/nsDirectoryService.cpp =================================================================== RCS file: /cvsroot/mozilla/xpcom/io/nsDirectoryService.cpp,v retrieving revision 1.94 diff -p -u -B -U 10 -r1.94 nsDirectoryService.cpp --- xpcom/io/nsDirectoryService.cpp 8 Jul 2007 07:08:51 -0000 1.94 +++ xpcom/io/nsDirectoryService.cpp 10 Oct 2007 20:19:17 -0000 @@ -351,20 +351,28 @@ nsIAtom* nsDirectoryService::sCommon_Pr nsIAtom* nsDirectoryService::sCommon_Startup = nsnull; nsIAtom* nsDirectoryService::sCommon_Desktopdirectory = nsnull; nsIAtom* nsDirectoryService::sAppdata = nsnull; nsIAtom* nsDirectoryService::sLocalAppdata = nsnull; nsIAtom* nsDirectoryService::sPrinthood = nsnull; nsIAtom* nsDirectoryService::sWinCookiesDirectory = nsnull; nsIAtom* nsDirectoryService::sDefaultDownloadDirectory = nsnull; #elif defined (XP_UNIX) nsIAtom* nsDirectoryService::sLocalDirectory = nsnull; nsIAtom* nsDirectoryService::sLibDirectory = nsnull; +nsIAtom* nsDirectoryService::sXDGDesktop = nsnull; +nsIAtom* nsDirectoryService::sXDGDocuments = nsnull; +nsIAtom* nsDirectoryService::sXDGDownload = nsnull; +nsIAtom* nsDirectoryService::sXDGMusic = nsnull; +nsIAtom* nsDirectoryService::sXDGPictures = nsnull; +nsIAtom* nsDirectoryService::sXDGPublicShare = nsnull; +nsIAtom* nsDirectoryService::sXDGTemplates = nsnull; +nsIAtom* nsDirectoryService::sXDGVideos = nsnull; #elif defined (XP_OS2) nsIAtom* nsDirectoryService::sSystemDirectory = nsnull; nsIAtom* nsDirectoryService::sOS2Directory = nsnull; #elif defined (XP_BEOS) nsIAtom* nsDirectoryService::sSettingsDirectory = nsnull; nsIAtom* nsDirectoryService::sSystemDirectory = nsnull; #endif nsDirectoryService* nsDirectoryService::gService = nsnull; @@ -458,20 +466,28 @@ static const nsStaticAtom directory_atom { NS_WIN_COMMON_STARTUP_DIR, &nsDirectoryService::sCommon_Startup }, { NS_WIN_COMMON_DESKTOP_DIRECTORY, &nsDirectoryService::sCommon_Desktopdirectory }, { NS_WIN_APPDATA_DIR, &nsDirectoryService::sAppdata }, { NS_WIN_LOCAL_APPDATA_DIR, &nsDirectoryService::sLocalAppdata }, { NS_WIN_PRINTHOOD, &nsDirectoryService::sPrinthood }, { NS_WIN_COOKIES_DIR, &nsDirectoryService::sWinCookiesDirectory }, { NS_WIN_DEFAULT_DOWNLOAD_DIR, &nsDirectoryService::sDefaultDownloadDirectory }, #elif defined (XP_UNIX) { NS_UNIX_LOCAL_DIR, &nsDirectoryService::sLocalDirectory }, { NS_UNIX_LIB_DIR, &nsDirectoryService::sLibDirectory }, + { NS_UNIX_XDG_DESKTOP_DIR, &nsDirectoryService::sXDGDesktop }, + { NS_UNIX_XDG_DOCUMENTS_DIR, &nsDirectoryService::sXDGDocuments }, + { NS_UNIX_XDG_DOWNLOAD_DIR, &nsDirectoryService::sXDGDownload }, + { NS_UNIX_XDG_MUSIC_DIR, &nsDirectoryService::sXDGMusic }, + { NS_UNIX_XDG_PICTURES_DIR, &nsDirectoryService::sXDGPictures }, + { NS_UNIX_XDG_PUBLIC_SHARE_DIR, &nsDirectoryService::sXDGPublicShare }, + { NS_UNIX_XDG_TEMPLATES_DIR, &nsDirectoryService::sXDGTemplates }, + { NS_UNIX_XDG_VIDEOS_DIR, &nsDirectoryService::sXDGVideos }, #elif defined (XP_OS2) { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory }, { NS_OS2_DIR, &nsDirectoryService::sOS2Directory }, #elif defined (XP_BEOS) { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory }, { NS_BEOS_SETTINGS_DIR, &nsDirectoryService::sSettingsDirectory }, #endif }; NS_IMETHODIMP @@ -1145,21 +1161,53 @@ nsDirectoryService::GetFile(const char * else if (inAtom == nsDirectoryService::sLibDirectory) { rv = GetSpecialSystemDirectory(Unix_LibDirectory, getter_AddRefs(localFile)); } else if (inAtom == nsDirectoryService::sOS_HomeDirectory) { rv = GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(localFile)); } else if (inAtom == nsDirectoryService::sOS_DesktopDirectory) { - rv = GetSpecialSystemDirectory(Unix_DesktopDirectory, getter_AddRefs(localFile)); + rv = GetSpecialSystemDirectory(Unix_XDG_Desktop, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGDesktop) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Desktop, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGDocuments) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Documents, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGDownload) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Download, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGMusic) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Music, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGPictures) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Pictures, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGPublicShare) + { + rv = GetSpecialSystemDirectory(Unix_XDG_PublicShare, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGTemplates) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Templates, getter_AddRefs(localFile)); + } + else if (inAtom == nsDirectoryService::sXDGVideos) + { + rv = GetSpecialSystemDirectory(Unix_XDG_Videos, getter_AddRefs(localFile)); } #elif defined (XP_OS2) else if (inAtom == nsDirectoryService::sSystemDirectory) { rv = GetSpecialSystemDirectory(OS2_SystemDirectory, getter_AddRefs(localFile)); } else if (inAtom == nsDirectoryService::sOS2Directory) { rv = GetSpecialSystemDirectory(OS2_OS2Directory, getter_AddRefs(localFile)); } Index: xpcom/io/nsDirectoryService.h =================================================================== RCS file: /cvsroot/mozilla/xpcom/io/nsDirectoryService.h,v retrieving revision 1.34 diff -p -u -B -U 10 -r1.34 nsDirectoryService.h --- xpcom/io/nsDirectoryService.h 24 Oct 2006 20:56:13 -0000 1.34 +++ xpcom/io/nsDirectoryService.h 10 Oct 2007 20:19:17 -0000 @@ -153,20 +153,28 @@ public: static nsIAtom *sCommon_Startup; static nsIAtom *sCommon_Desktopdirectory; static nsIAtom *sAppdata; static nsIAtom *sLocalAppdata; static nsIAtom *sPrinthood; static nsIAtom *sWinCookiesDirectory; static nsIAtom *sDefaultDownloadDirectory; #elif defined (XP_UNIX) static nsIAtom *sLocalDirectory; static nsIAtom *sLibDirectory; + static nsIAtom *sXDGDesktop; + static nsIAtom *sXDGDocuments; + static nsIAtom *sXDGDownload; + static nsIAtom *sXDGMusic; + static nsIAtom *sXDGPictures; + static nsIAtom *sXDGPublicShare; + static nsIAtom *sXDGTemplates; + static nsIAtom *sXDGVideos; #elif defined (XP_OS2) static nsIAtom *sSystemDirectory; static nsIAtom *sOS2Directory; #elif defined (XP_BEOS) static nsIAtom *sSettingsDirectory; static nsIAtom *sSystemDirectory; #endif }; Index: xpcom/io/nsDirectoryServiceDefs.h =================================================================== RCS file: /cvsroot/mozilla/xpcom/io/nsDirectoryServiceDefs.h,v retrieving revision 1.30 diff -p -u -B -U 10 -r1.30 nsDirectoryServiceDefs.h --- xpcom/io/nsDirectoryServiceDefs.h 24 Oct 2006 20:56:13 -0000 1.30 +++ xpcom/io/nsDirectoryServiceDefs.h 10 Oct 2007 20:19:17 -0000 @@ -176,8 +176,16 @@ #elif defined (XP_UNIX) #define NS_UNIX_LOCAL_DIR "Locl" #define NS_UNIX_LIB_DIR "LibD" #define NS_UNIX_HOME_DIR NS_OS_HOME_DIR + #define NS_UNIX_XDG_DESKTOP_DIR "XDGDesk" + #define NS_UNIX_XDG_DOCUMENTS_DIR "XDGDocs" + #define NS_UNIX_XDG_DOWNLOAD_DIR "XDGDwnld" + #define NS_UNIX_XDG_MUSIC_DIR "XDGMusic" + #define NS_UNIX_XDG_PICTURES_DIR "XDGPict" + #define NS_UNIX_XDG_PUBLIC_SHARE_DIR "XDGPubSh" + #define NS_UNIX_XDG_TEMPLATES_DIR "XDGTempl" + #define NS_UNIX_XDG_VIDEOS_DIR "XDGVids" #elif defined (XP_OS2) #define NS_OS2_DIR "OS2Dir" #define NS_OS2_HOME_DIR NS_OS_HOME_DIR #define NS_OS2_DESKTOP_DIR NS_OS_DESKTOP_DIR