summaryrefslogtreecommitdiff
path: root/indra/llfilesystem
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llfilesystem')
-rw-r--r--indra/llfilesystem/lldir.cpp1494
-rw-r--r--indra/llfilesystem/lldir.h420
2 files changed, 957 insertions, 957 deletions
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index 750d4e21b9..49d5b4fbdb 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldir.cpp
* @brief implementation of directory utilities base class
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,7 +37,7 @@
#include "lldir.h"
#include "llerror.h"
-#include "lltimer.h" // ms_sleep()
+#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#include "lldiriterator.h"
@@ -69,28 +69,28 @@ LLDir *gDirUtilp = (LLDir *)&gDirUtil;
/// Values for findSkinnedFilenames(subdir) parameter
const char
- *LLDir::XUI = "xui",
- *LLDir::TEXTURES = "textures",
- *LLDir::SKINBASE = "";
+ *LLDir::XUI = "xui",
+ *LLDir::TEXTURES = "textures",
+ *LLDir::SKINBASE = "";
static const char* const empty = "";
std::string LLDir::sDumpDir = "";
LLDir::LLDir()
-: mAppName(""),
- mExecutablePathAndName(""),
- mExecutableFilename(""),
- mExecutableDir(""),
- mAppRODataDir(""),
- mOSUserDir(""),
- mOSUserAppDir(""),
- mLindenUserDir(""),
- mOSCacheDir(""),
- mCAFile(""),
- mTempDir(""),
- mDirDelimiter("/"), // fallback to forward slash if not overridden
- mLanguage("en"),
- mUserName("undefined")
+: mAppName(""),
+ mExecutablePathAndName(""),
+ mExecutableFilename(""),
+ mExecutableDir(""),
+ mAppRODataDir(""),
+ mOSUserDir(""),
+ mOSUserAppDir(""),
+ mLindenUserDir(""),
+ mOSCacheDir(""),
+ mCAFile(""),
+ mTempDir(""),
+ mDirDelimiter("/"), // fallback to forward slash if not overridden
+ mLanguage("en"),
+ mUserName("undefined")
{
}
@@ -109,7 +109,7 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
#endif
std::vector<std::string> v;
-
+
if (exists(p))
{
if (is_directory(p))
@@ -127,188 +127,188 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
}
}
return v;
-}
-
+}
+
S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
{
- S32 count = 0;
- std::string filename;
- std::string fullpath;
- S32 result;
-
- // File masks starting with "/" will match nothing, so we consider them invalid.
- if (LLStringUtil::startsWith(mask, getDirDelimiter()))
- {
- LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL;
- llassert(!"Invalid file mask");
- }
-
- LLDirIterator iter(dirname, mask);
- while (iter.next(filename))
- {
- fullpath = add(dirname, filename);
-
- if(LLFile::isdir(fullpath))
- {
- // skipping directory traversal filenames
- count++;
- continue;
- }
-
- S32 retry_count = 0;
- while (retry_count < 5)
- {
- if (0 != LLFile::remove(fullpath))
- {
- retry_count++;
- result = errno;
- LL_WARNS() << "Problem removing " << fullpath << " - errorcode: "
- << result << " attempt " << retry_count << LL_ENDL;
-
- if(retry_count >= 5)
- {
- LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ;
- return count ;
- }
-
- ms_sleep(100);
- }
- else
- {
- if (retry_count)
- {
- LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL;
- }
- break;
- }
- }
- count++;
- }
- return count;
+ S32 count = 0;
+ std::string filename;
+ std::string fullpath;
+ S32 result;
+
+ // File masks starting with "/" will match nothing, so we consider them invalid.
+ if (LLStringUtil::startsWith(mask, getDirDelimiter()))
+ {
+ LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL;
+ llassert(!"Invalid file mask");
+ }
+
+ LLDirIterator iter(dirname, mask);
+ while (iter.next(filename))
+ {
+ fullpath = add(dirname, filename);
+
+ if(LLFile::isdir(fullpath))
+ {
+ // skipping directory traversal filenames
+ count++;
+ continue;
+ }
+
+ S32 retry_count = 0;
+ while (retry_count < 5)
+ {
+ if (0 != LLFile::remove(fullpath))
+ {
+ retry_count++;
+ result = errno;
+ LL_WARNS() << "Problem removing " << fullpath << " - errorcode: "
+ << result << " attempt " << retry_count << LL_ENDL;
+
+ if(retry_count >= 5)
+ {
+ LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ;
+ return count ;
+ }
+
+ ms_sleep(100);
+ }
+ else
+ {
+ if (retry_count)
+ {
+ LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL;
+ }
+ break;
+ }
+ }
+ count++;
+ }
+ return count;
}
U32 LLDir::deleteDirAndContents(const std::string& dir_name)
{
//Removes the directory and its contents. Returns number of files deleted.
-
- U32 num_deleted = 0;
- try
- {
+ U32 num_deleted = 0;
+
+ try
+ {
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));
+ boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));
#else
- boost::filesystem::path dir_path(dir_name);
+ boost::filesystem::path dir_path(dir_name);
#endif
- if (boost::filesystem::exists (dir_path))
- {
- if (!boost::filesystem::is_empty (dir_path))
- { // Directory has content
- num_deleted = boost::filesystem::remove_all (dir_path);
- }
- else
- { // Directory is empty
- boost::filesystem::remove (dir_path);
- }
- }
- }
- catch (boost::filesystem::filesystem_error &er)
- {
- LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL;
- }
- return num_deleted;
-}
-
-const std::string LLDir::findFile(const std::string &filename,
- const std::string& searchPath1,
- const std::string& searchPath2,
- const std::string& searchPath3) const
-{
- std::vector<std::string> search_paths;
- search_paths.push_back(searchPath1);
- search_paths.push_back(searchPath2);
- search_paths.push_back(searchPath3);
- return findFile(filename, search_paths);
+ if (boost::filesystem::exists (dir_path))
+ {
+ if (!boost::filesystem::is_empty (dir_path))
+ { // Directory has content
+ num_deleted = boost::filesystem::remove_all (dir_path);
+ }
+ else
+ { // Directory is empty
+ boost::filesystem::remove (dir_path);
+ }
+ }
+ }
+ catch (boost::filesystem::filesystem_error &er)
+ {
+ LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL;
+ }
+ return num_deleted;
+}
+
+const std::string LLDir::findFile(const std::string &filename,
+ const std::string& searchPath1,
+ const std::string& searchPath2,
+ const std::string& searchPath3) const
+{
+ std::vector<std::string> search_paths;
+ search_paths.push_back(searchPath1);
+ search_paths.push_back(searchPath2);
+ search_paths.push_back(searchPath3);
+ return findFile(filename, search_paths);
}
const std::string LLDir::findFile(const std::string& filename, const std::vector<std::string> search_paths) const
{
- std::vector<std::string>::const_iterator search_path_iter;
- for (search_path_iter = search_paths.begin();
- search_path_iter != search_paths.end();
- ++search_path_iter)
- {
- if (!search_path_iter->empty())
- {
- std::string filename_and_path = (*search_path_iter);
- if (!filename.empty())
- {
- filename_and_path += getDirDelimiter() + filename;
- }
- if (fileExists(filename_and_path))
- {
- return filename_and_path;
- }
- }
- }
- return "";
+ std::vector<std::string>::const_iterator search_path_iter;
+ for (search_path_iter = search_paths.begin();
+ search_path_iter != search_paths.end();
+ ++search_path_iter)
+ {
+ if (!search_path_iter->empty())
+ {
+ std::string filename_and_path = (*search_path_iter);
+ if (!filename.empty())
+ {
+ filename_and_path += getDirDelimiter() + filename;
+ }
+ if (fileExists(filename_and_path))
+ {
+ return filename_and_path;
+ }
+ }
+ }
+ return "";
}
const std::string &LLDir::getExecutablePathAndName() const
{
- return mExecutablePathAndName;
+ return mExecutablePathAndName;
}
const std::string &LLDir::getExecutableFilename() const
{
- return mExecutableFilename;
+ return mExecutableFilename;
}
const std::string &LLDir::getExecutableDir() const
{
- return mExecutableDir;
+ return mExecutableDir;
}
const std::string &LLDir::getWorkingDir() const
{
- return mWorkingDir;
+ return mWorkingDir;
}
const std::string &LLDir::getAppName() const
{
- return mAppName;
+ return mAppName;
}
const std::string &LLDir::getAppRODataDir() const
{
- return mAppRODataDir;
+ return mAppRODataDir;
}
const std::string &LLDir::getOSUserDir() const
{
- return mOSUserDir;
+ return mOSUserDir;
}
const std::string &LLDir::getOSUserAppDir() const
{
- return mOSUserAppDir;
+ return mOSUserAppDir;
}
const std::string &LLDir::getLindenUserDir() const
{
- if (mLindenUserDir.empty())
- {
- LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL;
- }
+ if (mLindenUserDir.empty())
+ {
+ LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL;
+ }
- return mLindenUserDir;
+ return mLindenUserDir;
}
const std::string& LLDir::getChatLogsDir() const
{
- return mChatLogsDir;
+ return mChatLogsDir;
}
void LLDir::setDumpDir( const std::string& path )
@@ -326,14 +326,14 @@ const std::string &LLDir::getDumpDir() const
{
LLUUID uid;
uid.generate();
-
+
sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")
+ "dump-" + uid.asString();
- dir_exists_or_crash(sDumpDir);
+ dir_exists_or_crash(sDumpDir);
}
- return LLDir::sDumpDir;
+ return LLDir::sDumpDir;
}
bool LLDir::dumpDirExists() const
@@ -343,80 +343,80 @@ bool LLDir::dumpDirExists() const
const std::string &LLDir::getPerAccountChatLogsDir() const
{
- return mPerAccountChatLogsDir;
+ return mPerAccountChatLogsDir;
}
const std::string &LLDir::getTempDir() const
{
- return mTempDir;
+ return mTempDir;
}
const std::string LLDir::getCacheDir(bool get_default) const
{
- if (mCacheDir.empty() || get_default)
- {
- if (!mDefaultCacheDir.empty())
- { // Set at startup - can't set here due to const API
- return mDefaultCacheDir;
- }
-
- std::string res = buildSLOSCacheDir();
- return res;
- }
- else
- {
- return mCacheDir;
- }
+ if (mCacheDir.empty() || get_default)
+ {
+ if (!mDefaultCacheDir.empty())
+ { // Set at startup - can't set here due to const API
+ return mDefaultCacheDir;
+ }
+
+ std::string res = buildSLOSCacheDir();
+ return res;
+ }
+ else
+ {
+ return mCacheDir;
+ }
}
// Return the default cache directory
std::string LLDir::buildSLOSCacheDir() const
{
- std::string res;
- if (getOSCacheDir().empty())
- {
- if (getOSUserAppDir().empty())
- {
- res = "data";
- }
- else
- {
- res = add(getOSUserAppDir(), "cache");
- }
- }
- else
- {
- res = add(getOSCacheDir(), "SecondLife");
- }
- return res;
+ std::string res;
+ if (getOSCacheDir().empty())
+ {
+ if (getOSUserAppDir().empty())
+ {
+ res = "data";
+ }
+ else
+ {
+ res = add(getOSUserAppDir(), "cache");
+ }
+ }
+ else
+ {
+ res = add(getOSCacheDir(), "SecondLife");
+ }
+ return res;
}
const std::string &LLDir::getOSCacheDir() const
{
- return mOSCacheDir;
+ return mOSCacheDir;
}
const std::string &LLDir::getCAFile() const
{
- return mCAFile;
+ return mCAFile;
}
const std::string &LLDir::getDirDelimiter() const
{
- return mDirDelimiter;
+ return mDirDelimiter;
}
const std::string& LLDir::getDefaultSkinDir() const
{
- return mDefaultSkinDir;
+ return mDefaultSkinDir;
}
const std::string &LLDir::getSkinDir() const
{
- return mSkinDir;
+ return mSkinDir;
}
const std::string &LLDir::getUserDefaultSkinDir() const
@@ -426,263 +426,263 @@ const std::string &LLDir::getUserDefaultSkinDir() const
const std::string &LLDir::getUserSkinDir() const
{
- return mUserSkinDir;
+ return mUserSkinDir;
}
const std::string LLDir::getSkinBaseDir() const
{
- return mSkinBaseDir;
+ return mSkinBaseDir;
}
const std::string &LLDir::getLLPluginDir() const
{
- return mLLPluginDir;
+ return mLLPluginDir;
}
const std::string &LLDir::getUserName() const
{
- return mUserName;
+ return mUserName;
}
static std::string ELLPathToString(ELLPath location)
{
- typedef std::map<ELLPath, const char*> ELLPathMap;
+ typedef std::map<ELLPath, const char*> ELLPathMap;
#define ENT(symbol) (symbol, #symbol)
- static const ELLPathMap sMap = map_list_of
- ENT(LL_PATH_NONE)
- ENT(LL_PATH_USER_SETTINGS)
- ENT(LL_PATH_APP_SETTINGS)
- ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
- ENT(LL_PATH_CACHE)
- ENT(LL_PATH_CHARACTER)
- ENT(LL_PATH_HELP)
- ENT(LL_PATH_LOGS)
- ENT(LL_PATH_TEMP)
- ENT(LL_PATH_SKINS)
- ENT(LL_PATH_TOP_SKIN)
- ENT(LL_PATH_CHAT_LOGS)
- ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
- ENT(LL_PATH_USER_SKIN)
- ENT(LL_PATH_LOCAL_ASSETS)
- ENT(LL_PATH_EXECUTABLE)
- ENT(LL_PATH_DEFAULT_SKIN)
- ENT(LL_PATH_FONTS)
- ENT(LL_PATH_LAST)
+ static const ELLPathMap sMap = map_list_of
+ ENT(LL_PATH_NONE)
+ ENT(LL_PATH_USER_SETTINGS)
+ ENT(LL_PATH_APP_SETTINGS)
+ ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
+ ENT(LL_PATH_CACHE)
+ ENT(LL_PATH_CHARACTER)
+ ENT(LL_PATH_HELP)
+ ENT(LL_PATH_LOGS)
+ ENT(LL_PATH_TEMP)
+ ENT(LL_PATH_SKINS)
+ ENT(LL_PATH_TOP_SKIN)
+ ENT(LL_PATH_CHAT_LOGS)
+ ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
+ ENT(LL_PATH_USER_SKIN)
+ ENT(LL_PATH_LOCAL_ASSETS)
+ ENT(LL_PATH_EXECUTABLE)
+ ENT(LL_PATH_DEFAULT_SKIN)
+ ENT(LL_PATH_FONTS)
+ ENT(LL_PATH_LAST)
ENT(LL_PATH_SCRIPTS)
- ;
+ ;
#undef ENT
- ELLPathMap::const_iterator found = sMap.find(location);
- if (found != sMap.end())
- return found->second;
- return STRINGIZE("Invalid ELLPath value " << location);
+ ELLPathMap::const_iterator found = sMap.find(location);
+ if (found != sMap.end())
+ return found->second;
+ return STRINGIZE("Invalid ELLPath value " << location);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
- return getExpandedFilename(location, "", filename);
+ return getExpandedFilename(location, "", filename);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const
{
- return getExpandedFilename(location, "", subdir, filename);
+ return getExpandedFilename(location, "", subdir, filename);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const
{
- std::string prefix;
- switch (location)
- {
- case LL_PATH_NONE:
- // Do nothing
- break;
-
- case LL_PATH_APP_SETTINGS:
- prefix = add(getAppRODataDir(), "app_settings");
- break;
-
- case LL_PATH_CHARACTER:
- prefix = add(getAppRODataDir(), "character");
- break;
-
- case LL_PATH_HELP:
- prefix = "help";
- break;
-
- case LL_PATH_CACHE:
- prefix = getCacheDir();
- break;
-
+ std::string prefix;
+ switch (location)
+ {
+ case LL_PATH_NONE:
+ // Do nothing
+ break;
+
+ case LL_PATH_APP_SETTINGS:
+ prefix = add(getAppRODataDir(), "app_settings");
+ break;
+
+ case LL_PATH_CHARACTER:
+ prefix = add(getAppRODataDir(), "character");
+ break;
+
+ case LL_PATH_HELP:
+ prefix = "help";
+ break;
+
+ case LL_PATH_CACHE:
+ prefix = getCacheDir();
+ break;
+
case LL_PATH_DUMP:
prefix=getDumpDir();
break;
-
- case LL_PATH_USER_SETTINGS:
- prefix = add(getOSUserAppDir(), "user_settings");
- break;
-
- case LL_PATH_PER_SL_ACCOUNT:
- prefix = getLindenUserDir();
- if (prefix.empty())
- {
- // if we're asking for the per-SL-account directory but we haven't
- // logged in yet (or otherwise don't know the account name from
- // which to build this string), then intentionally return a blank
- // string to the caller and skip the below warning about a blank
- // prefix.
- LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: "
- << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "' => ''" << LL_ENDL;
- return std::string();
- }
- break;
-
- case LL_PATH_CHAT_LOGS:
- prefix = getChatLogsDir();
- break;
-
- case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
- prefix = getPerAccountChatLogsDir();
- if (prefix.empty())
- {
- // potentially directory was not set yet
- // intentionally return a blank string to the caller
- LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL;
- return std::string();
- }
- break;
-
- case LL_PATH_LOGS:
- prefix = add(getOSUserAppDir(), "logs");
- break;
-
- case LL_PATH_TEMP:
- prefix = getTempDir();
- break;
-
- case LL_PATH_TOP_SKIN:
- prefix = getSkinDir();
- break;
-
- case LL_PATH_DEFAULT_SKIN:
- prefix = getDefaultSkinDir();
- break;
-
- case LL_PATH_USER_SKIN:
- prefix = getUserSkinDir();
- break;
-
- case LL_PATH_SKINS:
- prefix = getSkinBaseDir();
- break;
-
- case LL_PATH_LOCAL_ASSETS:
- prefix = add(getAppRODataDir(), "local_assets");
- break;
-
- case LL_PATH_EXECUTABLE:
- prefix = getExecutableDir();
- break;
-
- case LL_PATH_FONTS:
- prefix = add(getAppRODataDir(), "fonts");
- break;
+
+ case LL_PATH_USER_SETTINGS:
+ prefix = add(getOSUserAppDir(), "user_settings");
+ break;
+
+ case LL_PATH_PER_SL_ACCOUNT:
+ prefix = getLindenUserDir();
+ if (prefix.empty())
+ {
+ // if we're asking for the per-SL-account directory but we haven't
+ // logged in yet (or otherwise don't know the account name from
+ // which to build this string), then intentionally return a blank
+ // string to the caller and skip the below warning about a blank
+ // prefix.
+ LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: "
+ << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "' => ''" << LL_ENDL;
+ return std::string();
+ }
+ break;
+
+ case LL_PATH_CHAT_LOGS:
+ prefix = getChatLogsDir();
+ break;
+
+ case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
+ prefix = getPerAccountChatLogsDir();
+ if (prefix.empty())
+ {
+ // potentially directory was not set yet
+ // intentionally return a blank string to the caller
+ LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL;
+ return std::string();
+ }
+ break;
+
+ case LL_PATH_LOGS:
+ prefix = add(getOSUserAppDir(), "logs");
+ break;
+
+ case LL_PATH_TEMP:
+ prefix = getTempDir();
+ break;
+
+ case LL_PATH_TOP_SKIN:
+ prefix = getSkinDir();
+ break;
+
+ case LL_PATH_DEFAULT_SKIN:
+ prefix = getDefaultSkinDir();
+ break;
+
+ case LL_PATH_USER_SKIN:
+ prefix = getUserSkinDir();
+ break;
+
+ case LL_PATH_SKINS:
+ prefix = getSkinBaseDir();
+ break;
+
+ case LL_PATH_LOCAL_ASSETS:
+ prefix = add(getAppRODataDir(), "local_assets");
+ break;
+
+ case LL_PATH_EXECUTABLE:
+ prefix = getExecutableDir();
+ break;
+
+ case LL_PATH_FONTS:
+ prefix = add(getAppRODataDir(), "fonts");
+ break;
case LL_PATH_SCRIPTS:
prefix = add(getAppRODataDir(), "scripts");
break;
-
- default:
- llassert(0);
- }
-
- if (prefix.empty())
- {
- LL_WARNS() << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "': prefix is empty, possible bad filename" << LL_ENDL;
- }
-
- std::string expanded_filename = add(prefix, subdir1, subdir2);
- if (expanded_filename.empty() && in_filename.empty())
- {
- return "";
- }
- // Use explicit concatenation here instead of another add() call. Callers
- // passing in_filename as "" expect to obtain a pathname ending with
- // mDirSeparator so they can later directly concatenate with a specific
- // filename. A caller using add() doesn't care, but there's still code
- // loose in the system that uses std::string::operator+().
- expanded_filename += mDirDelimiter;
- expanded_filename += in_filename;
-
- LL_DEBUGS("LLDir") << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "' => '" << expanded_filename << "'" << LL_ENDL;
- return expanded_filename;
+
+ default:
+ llassert(0);
+ }
+
+ if (prefix.empty())
+ {
+ LL_WARNS() << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "': prefix is empty, possible bad filename" << LL_ENDL;
+ }
+
+ std::string expanded_filename = add(prefix, subdir1, subdir2);
+ if (expanded_filename.empty() && in_filename.empty())
+ {
+ return "";
+ }
+ // Use explicit concatenation here instead of another add() call. Callers
+ // passing in_filename as "" expect to obtain a pathname ending with
+ // mDirSeparator so they can later directly concatenate with a specific
+ // filename. A caller using add() doesn't care, but there's still code
+ // loose in the system that uses std::string::operator+().
+ expanded_filename += mDirDelimiter;
+ expanded_filename += in_filename;
+
+ LL_DEBUGS("LLDir") << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "' => '" << expanded_filename << "'" << LL_ENDL;
+ return expanded_filename;
}
std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const
{
- std::size_t offset = filepath.find_last_of(getDirDelimiter());
- offset = (offset == std::string::npos) ? 0 : offset+1;
- std::string res = filepath.substr(offset, std::string::npos);
- if (strip_exten)
- {
- offset = res.find_last_of('.');
- if (offset != std::string::npos &&
- offset != 0) // if basename STARTS with '.', don't strip
- {
- res = res.substr(0, offset);
- }
- }
- return res;
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ offset = (offset == std::string::npos) ? 0 : offset+1;
+ std::string res = filepath.substr(offset, std::string::npos);
+ if (strip_exten)
+ {
+ offset = res.find_last_of('.');
+ if (offset != std::string::npos &&
+ offset != 0) // if basename STARTS with '.', don't strip
+ {
+ res = res.substr(0, offset);
+ }
+ }
+ return res;
}
std::string LLDir::getDirName(const std::string& filepath) const
{
- std::size_t offset = filepath.find_last_of(getDirDelimiter());
- S32 len = (offset == std::string::npos) ? 0 : offset;
- std::string dirname = filepath.substr(0, len);
- return dirname;
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ S32 len = (offset == std::string::npos) ? 0 : offset;
+ std::string dirname = filepath.substr(0, len);
+ return dirname;
}
std::string LLDir::getExtension(const std::string& filepath) const
{
- if (filepath.empty())
- return std::string();
- std::string basename = getBaseFileName(filepath, false);
- std::size_t offset = basename.find_last_of('.');
- std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
- LLStringUtil::toLower(exten);
- return exten;
+ if (filepath.empty())
+ return std::string();
+ std::string basename = getBaseFileName(filepath, false);
+ std::size_t offset = basename.find_last_of('.');
+ std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
+ LLStringUtil::toLower(exten);
+ return exten;
}
std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint) const
+ const std::string &filename,
+ ESkinConstraint constraint) const
{
- // This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
- if (found.empty())
- {
- return "";
- }
- return found.front();
+ // This implementation is basically just as described in the declaration comments.
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
+ if (found.empty())
+ {
+ return "";
+ }
+ return found.front();
}
std::string LLDir::findSkinnedFilename(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint) const
+ const std::string &filename,
+ ESkinConstraint constraint) const
{
- // This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
- if (found.empty())
- {
- return "";
- }
- return found.back();
+ // This implementation is basically just as described in the declaration comments.
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
+ if (found.empty())
+ {
+ return "";
+ }
+ return found.back();
}
// This method exists because the two code paths for
@@ -691,210 +691,210 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir,
// difference is in the body of the inner loop.
template <typename FUNCTION>
void LLDir::walkSearchSkinDirs(const std::string& subdir,
- const std::vector<std::string>& subsubdirs,
- const std::string& filename,
- const FUNCTION& function) const
-{
- for (const std::string& skindir : mSearchSkinDirs)
- {
- std::string subdir_path(add(skindir, subdir));
- for (const std::string& subsubdir : subsubdirs)
- {
- std::string full_path(add(subdir_path, subsubdir, filename));
- if (fileExists(full_path))
- {
- function(subsubdir, full_path);
- }
- }
- }
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const
+{
+ for (const std::string& skindir : mSearchSkinDirs)
+ {
+ std::string subdir_path(add(skindir, subdir));
+ for (const std::string& subsubdir : subsubdirs)
+ {
+ std::string full_path(add(subdir_path, subsubdir, filename));
+ if (fileExists(full_path))
+ {
+ function(subsubdir, full_path);
+ }
+ }
+ }
}
// ridiculous little helper function that should go away when we can use lambda
inline void push_back(std::vector<std::string>& vector, const std::string& value)
{
- vector.push_back(value);
+ vector.push_back(value);
}
typedef std::map<std::string, std::string> StringMap;
// ridiculous little helper function that should go away when we can use lambda
inline void store_in_map(StringMap& map, const std::string& key, const std::string& value)
{
- map[key] = value;
+ map[key] = value;
}
std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
- const std::string& filename,
- ESkinConstraint constraint) const
-{
- // Recognize subdirs that have no localization.
- static const std::set<std::string> sUnlocalized = list_of
- ("") // top-level directory not localized
- ("textures") // textures not localized
- ;
-
- LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename
- << "', constraint "
- << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS")
- << LL_ENDL;
-
- // Build results vector.
- std::vector<std::string> results;
- // Disallow filenames that may escape subdir
- if (filename.find("..") != std::string::npos)
- {
- LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL;
- return results;
- }
-
- // Cache the default language directory for each subdir we've encountered.
- // A cache entry whose value is the empty string means "not localized,
- // don't bother checking again."
- static StringMap sLocalized;
-
- // Check whether we've already discovered if this subdir is localized.
- StringMap::const_iterator found = sLocalized.find(subdir);
- if (found == sLocalized.end())
- {
- // We have not yet determined that. Is it one of the subdirs "known"
- // to be unlocalized?
- if (sUnlocalized.find(subdir) != sUnlocalized.end())
- {
- // This subdir is known to be unlocalized. Remember that.
- found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
- }
- else
- {
- // We do not recognize this subdir. Investigate.
- std::string subdir_path(add(getDefaultSkinDir(), subdir));
- if (fileExists(add(subdir_path, "en")))
- {
- // defaultSkinDir/subdir contains subdir "en". That's our
- // default language; this subdir is localized.
- found = sLocalized.insert(StringMap::value_type(subdir, "en")).first;
- }
- else if (fileExists(add(subdir_path, "en-us")))
- {
- // defaultSkinDir/subdir contains subdir "en-us" but not "en".
- // Set as default language; this subdir is localized.
- found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first;
- }
- else
- {
- // defaultSkinDir/subdir contains neither "en" nor "en-us".
- // Assume it's not localized. Remember that assumption.
- found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
- }
- }
- }
- // Every code path above should have resulted in 'found' becoming a valid
- // iterator to an entry in sLocalized.
- llassert(found != sLocalized.end());
-
- // Now -- is this subdir localized, or not? The answer determines what
- // subdirectories we check (under subdir) for the requested filename.
- std::vector<std::string> subsubdirs;
- if (found->second.empty())
- {
- // subdir is not localized. filename should be located directly within it.
- subsubdirs.push_back("");
- }
- else
- {
- // subdir is localized, and found->second is the default language
- // directory within it. Check both the default language and the
- // current language -- if it differs from the default, of course.
- subsubdirs.push_back(found->second);
- if (mLanguage != found->second)
- {
- subsubdirs.push_back(mLanguage);
- }
- }
-
- // The process we use depends on 'constraint'.
- if (constraint != CURRENT_SKIN) // meaning ALL_SKINS
- {
- // ALL_SKINS is simpler: just return every pathname generated by
- // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its
- // FUNCTION the subsubdir as well as the full pathname. We just want
- // the full pathname.
- walkSearchSkinDirs(subdir, subsubdirs, filename,
- boost::bind(push_back, boost::ref(results), _2));
- }
- else // CURRENT_SKIN
- {
- // CURRENT_SKIN turns out to be a bit of a misnomer because we might
- // still return files from two different skins. In any case, this
- // value of 'constraint' means we will return at most two paths: one
- // for the default language, one for the current language (supposing
- // those differ).
- // It is important to allow a user to override only the localization
- // for a particular file, for all viewer installs, without also
- // overriding the default-language file.
- // It is important to allow a user to override only the default-
- // language file, for all viewer installs, without also overriding the
- // applicable localization of that file.
- // Therefore, treat the default language and the current language as
- // two separate cases. For each, capture the most-specialized file
- // that exists.
- // Use a map keyed by subsubdir (i.e. language code). This allows us
- // to handle the case of a single subsubdirs entry with the same logic
- // that handles two. For every real file path generated by
- // walkSearchSkinDirs(), update the map entry for its subsubdir.
- StringMap path_for;
- walkSearchSkinDirs(subdir, subsubdirs, filename,
- boost::bind(store_in_map, boost::ref(path_for), _1, _2));
- // Now that we have a path for each of the default language and the
- // current language, copy them -- in proper order -- into results.
- // Don't drive this by walking the map itself: it matters that we
- // generate results in the same order as subsubdirs.
- for (const std::string& subsubdir : subsubdirs)
- {
- StringMap::const_iterator found(path_for.find(subsubdir));
- if (found != path_for.end())
- {
- results.push_back(found->second);
- }
- }
- }
-
- LL_DEBUGS("LLDir") << empty;
- const char* comma = "";
- for (const std::string& path : results)
- {
- LL_CONT << comma << "'" << path << "'";
- comma = ", ";
- }
- LL_CONT << LL_ENDL;
-
- return results;
+ const std::string& filename,
+ ESkinConstraint constraint) const
+{
+ // Recognize subdirs that have no localization.
+ static const std::set<std::string> sUnlocalized = list_of
+ ("") // top-level directory not localized
+ ("textures") // textures not localized
+ ;
+
+ LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename
+ << "', constraint "
+ << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS")
+ << LL_ENDL;
+
+ // Build results vector.
+ std::vector<std::string> results;
+ // Disallow filenames that may escape subdir
+ if (filename.find("..") != std::string::npos)
+ {
+ LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL;
+ return results;
+ }
+
+ // Cache the default language directory for each subdir we've encountered.
+ // A cache entry whose value is the empty string means "not localized,
+ // don't bother checking again."
+ static StringMap sLocalized;
+
+ // Check whether we've already discovered if this subdir is localized.
+ StringMap::const_iterator found = sLocalized.find(subdir);
+ if (found == sLocalized.end())
+ {
+ // We have not yet determined that. Is it one of the subdirs "known"
+ // to be unlocalized?
+ if (sUnlocalized.find(subdir) != sUnlocalized.end())
+ {
+ // This subdir is known to be unlocalized. Remember that.
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
+ }
+ else
+ {
+ // We do not recognize this subdir. Investigate.
+ std::string subdir_path(add(getDefaultSkinDir(), subdir));
+ if (fileExists(add(subdir_path, "en")))
+ {
+ // defaultSkinDir/subdir contains subdir "en". That's our
+ // default language; this subdir is localized.
+ found = sLocalized.insert(StringMap::value_type(subdir, "en")).first;
+ }
+ else if (fileExists(add(subdir_path, "en-us")))
+ {
+ // defaultSkinDir/subdir contains subdir "en-us" but not "en".
+ // Set as default language; this subdir is localized.
+ found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first;
+ }
+ else
+ {
+ // defaultSkinDir/subdir contains neither "en" nor "en-us".
+ // Assume it's not localized. Remember that assumption.
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
+ }
+ }
+ }
+ // Every code path above should have resulted in 'found' becoming a valid
+ // iterator to an entry in sLocalized.
+ llassert(found != sLocalized.end());
+
+ // Now -- is this subdir localized, or not? The answer determines what
+ // subdirectories we check (under subdir) for the requested filename.
+ std::vector<std::string> subsubdirs;
+ if (found->second.empty())
+ {
+ // subdir is not localized. filename should be located directly within it.
+ subsubdirs.push_back("");
+ }
+ else
+ {
+ // subdir is localized, and found->second is the default language
+ // directory within it. Check both the default language and the
+ // current language -- if it differs from the default, of course.
+ subsubdirs.push_back(found->second);
+ if (mLanguage != found->second)
+ {
+ subsubdirs.push_back(mLanguage);
+ }
+ }
+
+ // The process we use depends on 'constraint'.
+ if (constraint != CURRENT_SKIN) // meaning ALL_SKINS
+ {
+ // ALL_SKINS is simpler: just return every pathname generated by
+ // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its
+ // FUNCTION the subsubdir as well as the full pathname. We just want
+ // the full pathname.
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(push_back, boost::ref(results), _2));
+ }
+ else // CURRENT_SKIN
+ {
+ // CURRENT_SKIN turns out to be a bit of a misnomer because we might
+ // still return files from two different skins. In any case, this
+ // value of 'constraint' means we will return at most two paths: one
+ // for the default language, one for the current language (supposing
+ // those differ).
+ // It is important to allow a user to override only the localization
+ // for a particular file, for all viewer installs, without also
+ // overriding the default-language file.
+ // It is important to allow a user to override only the default-
+ // language file, for all viewer installs, without also overriding the
+ // applicable localization of that file.
+ // Therefore, treat the default language and the current language as
+ // two separate cases. For each, capture the most-specialized file
+ // that exists.
+ // Use a map keyed by subsubdir (i.e. language code). This allows us
+ // to handle the case of a single subsubdirs entry with the same logic
+ // that handles two. For every real file path generated by
+ // walkSearchSkinDirs(), update the map entry for its subsubdir.
+ StringMap path_for;
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(store_in_map, boost::ref(path_for), _1, _2));
+ // Now that we have a path for each of the default language and the
+ // current language, copy them -- in proper order -- into results.
+ // Don't drive this by walking the map itself: it matters that we
+ // generate results in the same order as subsubdirs.
+ for (const std::string& subsubdir : subsubdirs)
+ {
+ StringMap::const_iterator found(path_for.find(subsubdir));
+ if (found != path_for.end())
+ {
+ results.push_back(found->second);
+ }
+ }
+ }
+
+ LL_DEBUGS("LLDir") << empty;
+ const char* comma = "";
+ for (const std::string& path : results)
+ {
+ LL_CONT << comma << "'" << path << "'";
+ comma = ", ";
+ }
+ LL_CONT << LL_ENDL;
+
+ return results;
}
std::string LLDir::getTempFilename() const
{
- LLUUID random_uuid;
- std::string uuid_str;
+ LLUUID random_uuid;
+ std::string uuid_str;
- random_uuid.generate();
- random_uuid.toString(uuid_str);
+ random_uuid.generate();
+ random_uuid.toString(uuid_str);
- return add(getTempDir(), uuid_str + ".tmp");
+ return add(getTempDir(), uuid_str + ".tmp");
}
// static
std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
{
- std::string name(uncleanFileName);
- const std::string illegalChars(getForbiddenFileChars());
- // replace any illegal file chars with and underscore '_'
- for( unsigned int i = 0; i < illegalChars.length(); i++ )
- {
- int j = -1;
- while((j = name.find(illegalChars[i])) > -1)
- {
- name[j] = '_';
- }
- }
- return name;
+ std::string name(uncleanFileName);
+ const std::string illegalChars(getForbiddenFileChars());
+ // replace any illegal file chars with and underscore '_'
+ for( unsigned int i = 0; i < illegalChars.length(); i++ )
+ {
+ int j = -1;
+ while((j = name.find(illegalChars[i])) > -1)
+ {
+ name[j] = '_';
+ }
+ }
+ return name;
}
std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
@@ -905,241 +905,241 @@ std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
// static
std::string LLDir::getForbiddenFileChars()
{
- return "\\/:*?\"<>|";
+ return "\\/:*?\"<>|";
}
void LLDir::setLindenUserDir(const std::string &username)
{
- // if the username isn't set, that's bad
- if (!username.empty())
- {
- // some platforms have case-sensitive filesystems, so be
- // utterly consistent with our firstname/lastname case.
- std::string userlower(username);
- LLStringUtil::toLower(userlower);
- LLStringUtil::replaceChar(userlower, ' ', '_');
- mLindenUserDir = add(getOSUserAppDir(), userlower);
- }
- else
- {
- LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL;
- }
+ // if the username isn't set, that's bad
+ if (!username.empty())
+ {
+ // some platforms have case-sensitive filesystems, so be
+ // utterly consistent with our firstname/lastname case.
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
+ mLindenUserDir = add(getOSUserAppDir(), userlower);
+ }
+ else
+ {
+ LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL;
+ }
- dumpCurrentDirectories();
+ dumpCurrentDirectories();
}
void LLDir::setChatLogsDir(const std::string &path)
{
- if (!path.empty() )
- {
- mChatLogsDir = path;
- }
- else
- {
- LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL;
- }
+ if (!path.empty() )
+ {
+ mChatLogsDir = path;
+ }
+ else
+ {
+ LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL;
+ }
}
void LLDir::updatePerAccountChatLogsDir()
{
- mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName);
+ mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName);
}
void LLDir::setPerAccountChatLogsDir(const std::string &username)
{
- // if both first and last aren't set, assume we're grabbing the cached dir
- if (!username.empty())
- {
- // some platforms have case-sensitive filesystems, so be
- // utterly consistent with our firstname/lastname case.
- std::string userlower(username);
- LLStringUtil::toLower(userlower);
- LLStringUtil::replaceChar(userlower, ' ', '_');
-
- mUserName = userlower;
- updatePerAccountChatLogsDir();
- }
- else
- {
- LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL;
- }
+ // if both first and last aren't set, assume we're grabbing the cached dir
+ if (!username.empty())
+ {
+ // some platforms have case-sensitive filesystems, so be
+ // utterly consistent with our firstname/lastname case.
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
+
+ mUserName = userlower;
+ updatePerAccountChatLogsDir();
+ }
+ else
+ {
+ LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL;
+ }
}
void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language)
{
- LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'"
- << LL_ENDL;
- mSkinName = skin_folder;
- mLanguage = language;
-
- // This method is called multiple times during viewer initialization. Each
- // time it's called, reset mSearchSkinDirs.
- mSearchSkinDirs.clear();
-
- // base skin which is used as fallback for all skinned files
- // e.g. c:\program files\secondlife\skins\default
- mDefaultSkinDir = getSkinBaseDir();
- append(mDefaultSkinDir, "default");
- // This is always the most general of the search skin directories.
- addSearchSkinDir(mDefaultSkinDir);
-
- mSkinDir = getSkinBaseDir();
- append(mSkinDir, skin_folder);
- // Next level of generality is a skin installed with the viewer.
- addSearchSkinDir(mSkinDir);
-
- // user modifications to skins, current and default
- // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
- mUserSkinDir = getOSUserAppDir();
- append(mUserSkinDir, "skins");
- mUserDefaultSkinDir = mUserSkinDir;
- append(mUserDefaultSkinDir, "default");
- append(mUserSkinDir, skin_folder);
- // Next level of generality is user modifications to default skin...
- addSearchSkinDir(mUserDefaultSkinDir);
- // then user-defined skins.
- addSearchSkinDir(mUserSkinDir);
+ LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'"
+ << LL_ENDL;
+ mSkinName = skin_folder;
+ mLanguage = language;
+
+ // This method is called multiple times during viewer initialization. Each
+ // time it's called, reset mSearchSkinDirs.
+ mSearchSkinDirs.clear();
+
+ // base skin which is used as fallback for all skinned files
+ // e.g. c:\program files\secondlife\skins\default
+ mDefaultSkinDir = getSkinBaseDir();
+ append(mDefaultSkinDir, "default");
+ // This is always the most general of the search skin directories.
+ addSearchSkinDir(mDefaultSkinDir);
+
+ mSkinDir = getSkinBaseDir();
+ append(mSkinDir, skin_folder);
+ // Next level of generality is a skin installed with the viewer.
+ addSearchSkinDir(mSkinDir);
+
+ // user modifications to skins, current and default
+ // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
+ mUserSkinDir = getOSUserAppDir();
+ append(mUserSkinDir, "skins");
+ mUserDefaultSkinDir = mUserSkinDir;
+ append(mUserDefaultSkinDir, "default");
+ append(mUserSkinDir, skin_folder);
+ // Next level of generality is user modifications to default skin...
+ addSearchSkinDir(mUserDefaultSkinDir);
+ // then user-defined skins.
+ addSearchSkinDir(mUserSkinDir);
}
void LLDir::addSearchSkinDir(const std::string& skindir)
{
- if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end())
- {
- LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL;
- mSearchSkinDirs.push_back(skindir);
- }
+ if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end())
+ {
+ LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL;
+ mSearchSkinDirs.push_back(skindir);
+ }
}
std::string LLDir::getSkinFolder() const
{
- return mSkinName;
+ return mSkinName;
}
std::string LLDir::getLanguage() const
{
- return mLanguage;
+ return mLanguage;
}
bool LLDir::setCacheDir(const std::string &path)
{
- if (path.empty() )
- {
- // reset to default
- mCacheDir = "";
- return true;
- }
- else
- {
- LLFile::mkdir(path);
- std::string tempname = add(path, "temp");
- LLFILE* file = LLFile::fopen(tempname,"wt");
- if (file)
- {
- fclose(file);
- LLFile::remove(tempname);
- mCacheDir = path;
- return true;
- }
- return false;
- }
+ if (path.empty() )
+ {
+ // reset to default
+ mCacheDir = "";
+ return true;
+ }
+ else
+ {
+ LLFile::mkdir(path);
+ std::string tempname = add(path, "temp");
+ LLFILE* file = LLFile::fopen(tempname,"wt");
+ if (file)
+ {
+ fclose(file);
+ LLFile::remove(tempname);
+ mCacheDir = path;
+ return true;
+ }
+ return false;
+ }
}
void LLDir::dumpCurrentDirectories(LLError::ELevel level)
{
- LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL;
-
- LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL;
+
+ LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
}
void LLDir::append(std::string& destpath, const std::string& name) const
{
- // Delegate question of whether we need a separator to helper method.
- SepOff sepoff(needSep(destpath, name));
- if (sepoff.first) // do we need a separator?
- {
- destpath += mDirDelimiter;
- }
- // If destpath ends with a separator, AND name starts with one, skip
- // name's leading separator.
- destpath += name.substr(sepoff.second);
+ // Delegate question of whether we need a separator to helper method.
+ SepOff sepoff(needSep(destpath, name));
+ if (sepoff.first) // do we need a separator?
+ {
+ destpath += mDirDelimiter;
+ }
+ // If destpath ends with a separator, AND name starts with one, skip
+ // name's leading separator.
+ destpath += name.substr(sepoff.second);
}
LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
{
- if (path.empty() || name.empty())
- {
- // If either path or name are empty, we do not need a separator
- // between them.
- return SepOff(false, 0);
- }
- // Here we know path and name are both non-empty. But if path already ends
- // with a separator, or if name already starts with a separator, we need
- // not add one.
- std::string::size_type seplen(mDirDelimiter.length());
- bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
- bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
- if ((! path_ends_sep) && (! name_starts_sep))
- {
- // If neither path nor name brings a separator to the junction, then
- // we need one.
- return SepOff(true, 0);
- }
- if (path_ends_sep && name_starts_sep)
- {
- // But if BOTH path and name bring a separator, we need not add one.
- // Moreover, we should actually skip the leading separator of 'name'.
- return SepOff(false, (unsigned short)seplen);
- }
- // Here we know that either path_ends_sep or name_starts_sep is true --
- // but not both. So don't add a separator, and don't skip any characters:
- // simple concatenation will do the trick.
- return SepOff(false, 0);
+ if (path.empty() || name.empty())
+ {
+ // If either path or name are empty, we do not need a separator
+ // between them.
+ return SepOff(false, 0);
+ }
+ // Here we know path and name are both non-empty. But if path already ends
+ // with a separator, or if name already starts with a separator, we need
+ // not add one.
+ std::string::size_type seplen(mDirDelimiter.length());
+ bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
+ bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
+ if ((! path_ends_sep) && (! name_starts_sep))
+ {
+ // If neither path nor name brings a separator to the junction, then
+ // we need one.
+ return SepOff(true, 0);
+ }
+ if (path_ends_sep && name_starts_sep)
+ {
+ // But if BOTH path and name bring a separator, we need not add one.
+ // Moreover, we should actually skip the leading separator of 'name'.
+ return SepOff(false, (unsigned short)seplen);
+ }
+ // Here we know that either path_ends_sep or name_starts_sep is true --
+ // but not both. So don't add a separator, and don't skip any characters:
+ // simple concatenation will do the trick.
+ return SepOff(false, 0);
}
void dir_exists_or_crash(const std::string &dir_name)
{
#if LL_WINDOWS
- // *FIX: lame - it doesn't do the same thing on windows. not so
- // important since we don't deploy simulator to windows boxes.
- LLFile::mkdir(dir_name, 0700);
+ // *FIX: lame - it doesn't do the same thing on windows. not so
+ // important since we don't deploy simulator to windows boxes.
+ LLFile::mkdir(dir_name, 0700);
#else
- struct stat dir_stat;
- if(0 != LLFile::stat(dir_name, &dir_stat))
- {
- S32 stat_rv = errno;
- if(ENOENT == stat_rv)
- {
- if(0 != LLFile::mkdir(dir_name, 0700)) // octal
- {
- LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL;
- }
- }
- else
- {
- LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv
- << LL_ENDL;
- }
- }
- else
- {
- // data_dir exists, make sure it's a directory.
- if(!S_ISDIR(dir_stat.st_mode))
- {
- LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL;
- }
- }
+ struct stat dir_stat;
+ if(0 != LLFile::stat(dir_name, &dir_stat))
+ {
+ S32 stat_rv = errno;
+ if(ENOENT == stat_rv)
+ {
+ if(0 != LLFile::mkdir(dir_name, 0700)) // octal
+ {
+ LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv
+ << LL_ENDL;
+ }
+ }
+ else
+ {
+ // data_dir exists, make sure it's a directory.
+ if(!S_ISDIR(dir_stat.st_mode))
+ {
+ LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL;
+ }
+ }
#endif
}
diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h
index 7d418159d1..560f63d40d 100644
--- a/indra/llfilesystem/lldir.h
+++ b/indra/llfilesystem/lldir.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldir.h
* @brief Definition of directory utilities class
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,246 +30,246 @@
// these numbers are read from settings_files.xml, so we need to be explicit
typedef enum ELLPath
{
- LL_PATH_NONE = 0,
- LL_PATH_USER_SETTINGS = 1,
- LL_PATH_APP_SETTINGS = 2,
- LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
- LL_PATH_CACHE = 4,
- LL_PATH_CHARACTER = 5,
- LL_PATH_HELP = 6,
- LL_PATH_LOGS = 7,
- LL_PATH_TEMP = 8,
- LL_PATH_SKINS = 9,
- LL_PATH_TOP_SKIN = 10,
- LL_PATH_CHAT_LOGS = 11,
- LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
- LL_PATH_USER_SKIN = 14,
- LL_PATH_LOCAL_ASSETS = 15,
- LL_PATH_EXECUTABLE = 16,
- LL_PATH_DEFAULT_SKIN = 17,
- LL_PATH_FONTS = 18,
+ LL_PATH_NONE = 0,
+ LL_PATH_USER_SETTINGS = 1,
+ LL_PATH_APP_SETTINGS = 2,
+ LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
+ LL_PATH_CACHE = 4,
+ LL_PATH_CHARACTER = 5,
+ LL_PATH_HELP = 6,
+ LL_PATH_LOGS = 7,
+ LL_PATH_TEMP = 8,
+ LL_PATH_SKINS = 9,
+ LL_PATH_TOP_SKIN = 10,
+ LL_PATH_CHAT_LOGS = 11,
+ LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
+ LL_PATH_USER_SKIN = 14,
+ LL_PATH_LOCAL_ASSETS = 15,
+ LL_PATH_EXECUTABLE = 16,
+ LL_PATH_DEFAULT_SKIN = 17,
+ LL_PATH_FONTS = 18,
LL_PATH_DUMP = 19,
LL_PATH_SCRIPTS = 20,
- LL_PATH_LAST
+ LL_PATH_LAST
} ELLPath;
/// Directory operations
class LLDir
{
public:
- LLDir();
- virtual ~LLDir();
+ LLDir();
+ virtual ~LLDir();
- // app_name - Usually SecondLife, used for creating settings directories
- // in OS-specific location, such as C:\Documents and Settings
- // app_read_only_data_dir - Usually the source code directory, used
- // for test applications to read newview data files.
- virtual void initAppDirs(const std::string &app_name,
- const std::string& app_read_only_data_dir = "") = 0;
+ // app_name - Usually SecondLife, used for creating settings directories
+ // in OS-specific location, such as C:\Documents and Settings
+ // app_read_only_data_dir - Usually the source code directory, used
+ // for test applications to read newview data files.
+ virtual void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir = "") = 0;
- virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
+ virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
U32 deleteDirAndContents(const std::string& dir_name);
std::vector<std::string> getFilesInDir(const std::string &dirname);
// pure virtual functions
- virtual std::string getCurPath() = 0;
- virtual bool fileExists(const std::string &filename) const = 0;
+ virtual std::string getCurPath() = 0;
+ virtual bool fileExists(const std::string &filename) const = 0;
- const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
- const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
+ const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
+ const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
- virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
- virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
+ virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
+ virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
- const std::string &getExecutablePathAndName() const; // Full pathname of the executable
- const std::string &getAppName() const; // install directory under progams/ ie "SecondLife"
- const std::string &getExecutableDir() const; // Directory where the executable is located
- const std::string &getExecutableFilename() const;// Filename of .exe
- const std::string &getWorkingDir() const; // Current working directory
- const std::string &getAppRODataDir() const; // Location of read-only data files
- const std::string &getOSUserDir() const; // Location of the os-specific user dir
- const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir
- const std::string &getLindenUserDir() const; // Location of the Linden user dir.
- const std::string &getChatLogsDir() const; // Location of the chat logs dir.
- const std::string &getDumpDir() const; // Location of the per-run dump dir.
- bool dumpDirExists() const;
- const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
- const std::string &getTempDir() const; // Common temporary directory
- const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
- const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string)
- const std::string &getCAFile() const; // File containing TLS certificate authorities
- const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':')
- const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
- const std::string &getSkinDir() const; // User-specified skin folder.
- const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin
- const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin
- const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins
- const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell
- const std::string &getUserName() const;
+ const std::string &getExecutablePathAndName() const; // Full pathname of the executable
+ const std::string &getAppName() const; // install directory under progams/ ie "SecondLife"
+ const std::string &getExecutableDir() const; // Directory where the executable is located
+ const std::string &getExecutableFilename() const;// Filename of .exe
+ const std::string &getWorkingDir() const; // Current working directory
+ const std::string &getAppRODataDir() const; // Location of read-only data files
+ const std::string &getOSUserDir() const; // Location of the os-specific user dir
+ const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir
+ const std::string &getLindenUserDir() const; // Location of the Linden user dir.
+ const std::string &getChatLogsDir() const; // Location of the chat logs dir.
+ const std::string &getDumpDir() const; // Location of the per-run dump dir.
+ bool dumpDirExists() const;
+ const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
+ const std::string &getTempDir() const; // Common temporary directory
+ const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
+ const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string)
+ const std::string &getCAFile() const; // File containing TLS certificate authorities
+ const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':')
+ const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
+ const std::string &getSkinDir() const; // User-specified skin folder.
+ const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin
+ const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin
+ const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins
+ const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell
+ const std::string &getUserName() const;
- // Expanded filename
- std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
- std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
- std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
+ // Expanded filename
+ std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
- // Base and Directory name extraction
- std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const;
- std::string getDirName(const std::string& filepath) const;
- std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav"
+ // Base and Directory name extraction
+ std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const;
+ std::string getDirName(const std::string& filepath) const;
+ std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav"
- // these methods search the various skin paths for the specified file in the following order:
- // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir()
- /// param value for findSkinnedFilenames(), explained below
- enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS };
- /**
- * Given a filename within skin, return an ordered sequence of paths to
- * search. Nonexistent files will be filtered out -- which means that the
- * vector might be empty.
- *
- * @param subdir Identify top-level skin subdirectory by passing one of
- * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file
- * lives under "textures" subtree), LLDir::SKINBASE (file lives at top
- * level of skin subdirectory).
- * @param filename Desired filename within subdir within skin, e.g.
- * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language.
- * @param constraint Callers perform two different kinds of processing.
- * When fetching a XUI file, for instance, the existence of @a filename in
- * the specified skin completely supercedes any @a filename in the default
- * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The
- * returned vector will contain only
- * ".../<i>current_skin</i>/xui/en/<i>filename</i>",
- * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>".
- * But for (e.g.) "strings.xml", we want a given skin to be able to
- * override only specific entries from the default skin. Any string not
- * defined in the specified skin will be sought in the default skin. For
- * that case, pass @a constraint=ALL_SKINS. The returned vector will
- * contain at least ".../default/xui/en/strings.xml",
- * ".../default/xui/<i>current_language</i>/strings.xml",
- * ".../<i>current_skin</i>/xui/en/strings.xml",
- * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml".
- */
- std::vector<std::string> findSkinnedFilenames(const std::string& subdir,
- const std::string& filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
- /// Values for findSkinnedFilenames(subdir) parameter
- static const char *XUI, *TEXTURES, *SKINBASE;
- /**
- * Return the base-language pathname from findSkinnedFilenames(), or
- * the empty string if no such file exists. Parameters are identical to
- * findSkinnedFilenames(). This is shorthand for capturing the vector
- * returned by findSkinnedFilenames(), checking for empty() and then
- * returning front().
- */
- std::string findSkinnedFilenameBaseLang(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
- /**
- * Return the "most localized" pathname from findSkinnedFilenames(), or
- * the empty string if no such file exists. Parameters are identical to
- * findSkinnedFilenames(). This is shorthand for capturing the vector
- * returned by findSkinnedFilenames(), checking for empty() and then
- * returning back().
- */
- std::string findSkinnedFilename(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
+ // these methods search the various skin paths for the specified file in the following order:
+ // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir()
+ /// param value for findSkinnedFilenames(), explained below
+ enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS };
+ /**
+ * Given a filename within skin, return an ordered sequence of paths to
+ * search. Nonexistent files will be filtered out -- which means that the
+ * vector might be empty.
+ *
+ * @param subdir Identify top-level skin subdirectory by passing one of
+ * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file
+ * lives under "textures" subtree), LLDir::SKINBASE (file lives at top
+ * level of skin subdirectory).
+ * @param filename Desired filename within subdir within skin, e.g.
+ * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language.
+ * @param constraint Callers perform two different kinds of processing.
+ * When fetching a XUI file, for instance, the existence of @a filename in
+ * the specified skin completely supercedes any @a filename in the default
+ * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The
+ * returned vector will contain only
+ * ".../<i>current_skin</i>/xui/en/<i>filename</i>",
+ * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>".
+ * But for (e.g.) "strings.xml", we want a given skin to be able to
+ * override only specific entries from the default skin. Any string not
+ * defined in the specified skin will be sought in the default skin. For
+ * that case, pass @a constraint=ALL_SKINS. The returned vector will
+ * contain at least ".../default/xui/en/strings.xml",
+ * ".../default/xui/<i>current_language</i>/strings.xml",
+ * ".../<i>current_skin</i>/xui/en/strings.xml",
+ * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml".
+ */
+ std::vector<std::string> findSkinnedFilenames(const std::string& subdir,
+ const std::string& filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
+ /// Values for findSkinnedFilenames(subdir) parameter
+ static const char *XUI, *TEXTURES, *SKINBASE;
+ /**
+ * Return the base-language pathname from findSkinnedFilenames(), or
+ * the empty string if no such file exists. Parameters are identical to
+ * findSkinnedFilenames(). This is shorthand for capturing the vector
+ * returned by findSkinnedFilenames(), checking for empty() and then
+ * returning front().
+ */
+ std::string findSkinnedFilenameBaseLang(const std::string &subdir,
+ const std::string &filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
+ /**
+ * Return the "most localized" pathname from findSkinnedFilenames(), or
+ * the empty string if no such file exists. Parameters are identical to
+ * findSkinnedFilenames(). This is shorthand for capturing the vector
+ * returned by findSkinnedFilenames(), checking for empty() and then
+ * returning back().
+ */
+ std::string findSkinnedFilename(const std::string &subdir,
+ const std::string &filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
- // random filename in common temporary directory
- std::string getTempFilename() const;
+ // random filename in common temporary directory
+ std::string getTempFilename() const;
static std::string getDumpLogsDirPath(const std::string &file_name = "");
- // For producing safe download file names from potentially unsafe ones
- static std::string getScrubbedFileName(const std::string uncleanFileName);
- static std::string getForbiddenFileChars();
+ // For producing safe download file names from potentially unsafe ones
+ static std::string getScrubbedFileName(const std::string uncleanFileName);
+ static std::string getForbiddenFileChars();
void setDumpDir( const std::string& path );
- virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
- virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory.
- virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir
- virtual void setSkinFolder(const std::string &skin_folder, const std::string& language);
- virtual std::string getSkinFolder() const;
- virtual std::string getLanguage() const;
- virtual bool setCacheDir(const std::string &path);
- virtual void updatePerAccountChatLogsDir();
+ virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
+ virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory.
+ virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir
+ virtual void setSkinFolder(const std::string &skin_folder, const std::string& language);
+ virtual std::string getSkinFolder() const;
+ virtual std::string getLanguage() const;
+ virtual bool setCacheDir(const std::string &path);
+ virtual void updatePerAccountChatLogsDir();
- virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG);
+ virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG);
- // Utility routine
- std::string buildSLOSCacheDir() const;
+ // Utility routine
+ std::string buildSLOSCacheDir() const;
- /// Append specified @a name to @a destpath, separated by getDirDelimiter()
- /// if both are non-empty.
- void append(std::string& destpath, const std::string& name) const;
- /// Variadic form: append @a name0 and @a name1 and arbitrary other @a
- /// names to @a destpath, separated by getDirDelimiter() as needed.
- template <typename... NAMES>
- void append(std::string& destpath, const std::string& name0, const std::string& name1,
- const NAMES& ... names) const
- {
- // In a typical recursion case, we'd accept (destpath, name0, names).
- // We accept (destpath, name0, name1, names) because it's important to
- // delegate the two-argument case to the non-template implementation.
- append(destpath, name0);
- append(destpath, name1, names...);
- }
+ /// Append specified @a name to @a destpath, separated by getDirDelimiter()
+ /// if both are non-empty.
+ void append(std::string& destpath, const std::string& name) const;
+ /// Variadic form: append @a name0 and @a name1 and arbitrary other @a
+ /// names to @a destpath, separated by getDirDelimiter() as needed.
+ template <typename... NAMES>
+ void append(std::string& destpath, const std::string& name0, const std::string& name1,
+ const NAMES& ... names) const
+ {
+ // In a typical recursion case, we'd accept (destpath, name0, names).
+ // We accept (destpath, name0, name1, names) because it's important to
+ // delegate the two-argument case to the non-template implementation.
+ append(destpath, name0);
+ append(destpath, name1, names...);
+ }
- /// Append specified @a names to @a path, separated by getDirDelimiter()
- /// as needed. Return result, leaving @a path unmodified.
- template <typename... NAMES>
- std::string add(const std::string& path, const NAMES& ... names) const
- {
- std::string destpath(path);
- append(destpath, names...);
- return destpath;
- }
+ /// Append specified @a names to @a path, separated by getDirDelimiter()
+ /// as needed. Return result, leaving @a path unmodified.
+ template <typename... NAMES>
+ std::string add(const std::string& path, const NAMES& ... names) const
+ {
+ std::string destpath(path);
+ append(destpath, names...);
+ return destpath;
+ }
protected:
- // Does an add() or append() call need a directory delimiter?
- typedef std::pair<bool, unsigned short> SepOff;
- SepOff needSep(const std::string& path, const std::string& name) const;
- // build mSearchSkinDirs without adding duplicates
- void addSearchSkinDir(const std::string& skindir);
+ // Does an add() or append() call need a directory delimiter?
+ typedef std::pair<bool, unsigned short> SepOff;
+ SepOff needSep(const std::string& path, const std::string& name) const;
+ // build mSearchSkinDirs without adding duplicates
+ void addSearchSkinDir(const std::string& skindir);
- // Internal to findSkinnedFilenames()
- template <typename FUNCTION>
- void walkSearchSkinDirs(const std::string& subdir,
- const std::vector<std::string>& subsubdirs,
- const std::string& filename,
- const FUNCTION& function) const;
+ // Internal to findSkinnedFilenames()
+ template <typename FUNCTION>
+ void walkSearchSkinDirs(const std::string& subdir,
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const;
- std::string mAppName; // install directory under progams/ ie "SecondLife"
- std::string mExecutablePathAndName; // full path + Filename of .exe
- std::string mExecutableFilename; // Filename of .exe
- std::string mExecutableDir; // Location of executable
- std::string mWorkingDir; // Current working directory
- std::string mAppRODataDir; // Location for static app data
- std::string mOSUserDir; // OS Specific user directory
- std::string mOSUserAppDir; // OS Specific user app directory
- std::string mLindenUserDir; // Location for Linden user-specific data
- std::string mPerAccountChatLogsDir; // Location for chat logs.
- std::string mChatLogsDir; // Location for chat logs.
- std::string mCAFile; // Location of the TLS certificate authority PEM file.
- std::string mTempDir;
- std::string mCacheDir; // cache directory as set by user preference
- std::string mDefaultCacheDir; // default cache diretory
- std::string mOSCacheDir; // operating system cache dir
- std::string mDirDelimiter;
- std::string mSkinName; // caller-specified skin name
- std::string mSkinBaseDir; // Base for skins paths.
- std::string mDefaultSkinDir; // Location for default skin info.
- std::string mSkinDir; // Location for current skin info.
- std::string mUserDefaultSkinDir; // Location for default skin info.
- std::string mUserSkinDir; // Location for user-modified skin info.
- // Skin directories to search, most general to most specific. This order
- // works well for composing fine-grained files, in which an individual item
- // in a specific file overrides the corresponding item in more general
- // files. Of course, for a file-level search, iterate backwards.
- std::vector<std::string> mSearchSkinDirs;
- std::string mLanguage; // Current viewer language
- std::string mLLPluginDir; // Location for plugins and plugin shell
+ std::string mAppName; // install directory under progams/ ie "SecondLife"
+ std::string mExecutablePathAndName; // full path + Filename of .exe
+ std::string mExecutableFilename; // Filename of .exe
+ std::string mExecutableDir; // Location of executable
+ std::string mWorkingDir; // Current working directory
+ std::string mAppRODataDir; // Location for static app data
+ std::string mOSUserDir; // OS Specific user directory
+ std::string mOSUserAppDir; // OS Specific user app directory
+ std::string mLindenUserDir; // Location for Linden user-specific data
+ std::string mPerAccountChatLogsDir; // Location for chat logs.
+ std::string mChatLogsDir; // Location for chat logs.
+ std::string mCAFile; // Location of the TLS certificate authority PEM file.
+ std::string mTempDir;
+ std::string mCacheDir; // cache directory as set by user preference
+ std::string mDefaultCacheDir; // default cache diretory
+ std::string mOSCacheDir; // operating system cache dir
+ std::string mDirDelimiter;
+ std::string mSkinName; // caller-specified skin name
+ std::string mSkinBaseDir; // Base for skins paths.
+ std::string mDefaultSkinDir; // Location for default skin info.
+ std::string mSkinDir; // Location for current skin info.
+ std::string mUserDefaultSkinDir; // Location for default skin info.
+ std::string mUserSkinDir; // Location for user-modified skin info.
+ // Skin directories to search, most general to most specific. This order
+ // works well for composing fine-grained files, in which an individual item
+ // in a specific file overrides the corresponding item in more general
+ // files. Of course, for a file-level search, iterate backwards.
+ std::vector<std::string> mSearchSkinDirs;
+ std::string mLanguage; // Current viewer language
+ std::string mLLPluginDir; // Location for plugins and plugin shell
static std::string sDumpDir; // Per-run crash report subdir of log directory.
- std::string mUserName; // Current user name
+ std::string mUserName; // Current user name
};
void dir_exists_or_crash(const std::string &dir_name);