llrender and lldir merge. Removed duplicate assets from skins. cleaned up skin textures.xml files to only include changes from default.
This commit is contained in:
@@ -71,8 +71,15 @@ LLDir_Linux gDirUtil;
|
||||
|
||||
LLDir *gDirUtilp = (LLDir *)&gDirUtil;
|
||||
|
||||
/// Values for findSkinnedFilenames(subdir) parameter
|
||||
const char
|
||||
*LLDir::XUI = "xui",
|
||||
*LLDir::TEXTURES = "textures",
|
||||
*LLDir::SKINBASE = "";
|
||||
|
||||
static const char* const empty = "";
|
||||
std::string LLDir::sDumpDir = "";
|
||||
|
||||
LLDir::LLDir()
|
||||
: mAppName(""),
|
||||
mExecutablePathAndName(""),
|
||||
@@ -85,7 +92,9 @@ LLDir::LLDir()
|
||||
mOSCacheDir(""),
|
||||
mCAFile(""),
|
||||
mTempDir(""),
|
||||
mDirDelimiter("/") // fallback to forward slash if not overridden
|
||||
mDirDelimiter("/"), // fallback to forward slash if not overridden
|
||||
mLanguage("en"),
|
||||
mUserName("undefined")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -97,7 +106,11 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
|
||||
{
|
||||
//Returns a vector of fullpath filenames.
|
||||
|
||||
#if LL_WINDOWS
|
||||
boost::filesystem::path p (utf8str_to_utf16str(dirname).c_str());
|
||||
#else
|
||||
boost::filesystem::path p (dirname);
|
||||
#endif
|
||||
std::vector<std::string> v;
|
||||
|
||||
if (exists(p))
|
||||
@@ -188,19 +201,33 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
|
||||
U32 LLDir::deleteDirAndContents(const std::string& dir_name)
|
||||
{
|
||||
//Removes the directory and its contents. Returns number of files removed.
|
||||
// Singu Note: boost::filesystem throws exceptions
|
||||
S32 res = 0;
|
||||
|
||||
U32 num_deleted = 0;
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
res = boost::filesystem::remove_all(dir_name);
|
||||
#if LL_WINDOWS
|
||||
boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name).c_str());
|
||||
#else
|
||||
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(const boost::filesystem::filesystem_error& e)
|
||||
{
|
||||
LL_WARNS() << "boost::filesystem::remove_all(\"" + dir_name + "\") failed: '" + e.code().message() + "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
return res;
|
||||
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,
|
||||
@@ -346,6 +373,12 @@ const std::string LLDir::getCacheDir(bool get_default) const
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__))
|
||||
#define OS_CACHE_DIR "SingularityViewer64"
|
||||
#else
|
||||
#define OS_CACHE_DIR "Obsidian"
|
||||
#endif
|
||||
|
||||
// Return the default cache directory
|
||||
std::string LLDir::buildSLOSCacheDir() const
|
||||
{
|
||||
@@ -363,11 +396,7 @@ std::string LLDir::buildSLOSCacheDir() const
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
res = add(getOSCacheDir(), "SingularityViewer64");
|
||||
#else
|
||||
res = add(getOSCacheDir(), "SingularityViewer");
|
||||
#endif
|
||||
res = add(getOSCacheDir(), OS_CACHE_DIR);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -390,20 +419,26 @@ const std::string &LLDir::getDirDelimiter() const
|
||||
return mDirDelimiter;
|
||||
}
|
||||
|
||||
const std::string& LLDir::getDefaultSkinDir() const
|
||||
{
|
||||
return mDefaultSkinDir;
|
||||
}
|
||||
|
||||
const std::string &LLDir::getSkinDir() const
|
||||
{
|
||||
return mSkinDir;
|
||||
}
|
||||
|
||||
const std::string& LLDir::getUserDefaultSkinDir() const
|
||||
{
|
||||
return mUserDefaultSkinDir;
|
||||
}
|
||||
|
||||
const std::string &LLDir::getUserSkinDir() const
|
||||
{
|
||||
return mUserSkinDir;
|
||||
}
|
||||
|
||||
const std::string& LLDir::getDefaultSkinDir() const
|
||||
{
|
||||
return mDefaultSkinDir;
|
||||
}
|
||||
|
||||
const std::string LLDir::getSkinBaseDir() const
|
||||
{
|
||||
@@ -415,6 +450,11 @@ const std::string &LLDir::getLLPluginDir() const
|
||||
return mLLPluginDir;
|
||||
}
|
||||
|
||||
const std::string &LLDir::getUserName() const
|
||||
{
|
||||
return mUserName;
|
||||
}
|
||||
|
||||
static std::string ELLPathToString(ELLPath location)
|
||||
{
|
||||
typedef std::map<ELLPath, const char*> ELLPathMap;
|
||||
@@ -602,7 +642,7 @@ std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten
|
||||
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;
|
||||
size_t len = (offset == std::string::npos) ? 0 : offset;
|
||||
std::string dirname = filepath.substr(0, len);
|
||||
return dirname;
|
||||
}
|
||||
@@ -618,31 +658,207 @@ std::string LLDir::getExtension(const std::string& filepath) const
|
||||
return exten;
|
||||
}
|
||||
|
||||
std::string LLDir::findSkinnedFilename(const std::string &filename) const
|
||||
std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir,
|
||||
const std::string &filename,
|
||||
ESkinConstraint constraint) const
|
||||
{
|
||||
return findSkinnedFilename("", "", filename);
|
||||
// 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) const
|
||||
std::string LLDir::findSkinnedFilename(const std::string &subdir,
|
||||
const std::string &filename,
|
||||
ESkinConstraint constraint) const
|
||||
{
|
||||
return findSkinnedFilename("", subdir, filename);
|
||||
// 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();
|
||||
}
|
||||
|
||||
std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const
|
||||
// This method exists because the two code paths for
|
||||
// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must
|
||||
// generate the list of candidate pathnames in identical ways. The only
|
||||
// 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
|
||||
{
|
||||
// generate subdirectory path fragment, e.g. "/foo/bar", "/foo", ""
|
||||
std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1)
|
||||
+ ((subdir2.empty() ? "" : mDirDelimiter) + subdir2);
|
||||
BOOST_FOREACH(std::string skindir, mSearchSkinDirs)
|
||||
{
|
||||
std::string subdir_path(add(skindir, subdir));
|
||||
BOOST_FOREACH(std::string subsubdir, subsubdirs)
|
||||
{
|
||||
std::string full_path(add(add(subdir_path, subsubdir), filename));
|
||||
if (fileExists(full_path))
|
||||
{
|
||||
function(subsubdir, full_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> search_paths;
|
||||
|
||||
search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override
|
||||
search_paths.push_back(getSkinDir() + subdirs); // then in current skin
|
||||
search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin
|
||||
search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory
|
||||
// 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);
|
||||
}
|
||||
|
||||
std::string found_file = findFile(filename, search_paths);
|
||||
return found_file;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Build results vector.
|
||||
std::vector<std::string> results;
|
||||
// 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.
|
||||
BOOST_FOREACH(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 = "";
|
||||
BOOST_FOREACH(std::string path, results)
|
||||
{
|
||||
LL_CONT << comma << "'" << path << "'";
|
||||
comma = ", ";
|
||||
}
|
||||
LL_CONT << LL_ENDL;
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::string LLDir::getTempFilename() const
|
||||
@@ -657,7 +873,7 @@ std::string LLDir::getTempFilename() const
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
|
||||
std::string LLDir::getScrubbedFileName(const std::string& uncleanFileName)
|
||||
{
|
||||
std::string name(uncleanFileName);
|
||||
std::string illegalChars(getForbiddenFileChars());
|
||||
@@ -668,8 +884,8 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
|
||||
// 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)
|
||||
size_t j = std::string::npos;
|
||||
while ((j = name.find(illegalChars[i])) != std::string::npos)
|
||||
{
|
||||
name[j] = '_';
|
||||
}
|
||||
@@ -683,6 +899,19 @@ std::string LLDir::getForbiddenFileChars()
|
||||
return "\\/:*?\"<>|";
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLDir::getGridSpecificDir( const std::string& in, const std::string& grid )
|
||||
{
|
||||
std::string ret;
|
||||
if (!grid.empty())
|
||||
{
|
||||
std::string gridlower(grid);
|
||||
LLStringUtil::toLower(gridlower);
|
||||
ret = in + "@" + gridlower;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLDir::setLindenUserDir(const std::string &grid, const std::string &first, const std::string &last)
|
||||
{
|
||||
// if both first and last aren't set, assume we're grabbing the cached dir
|
||||
@@ -692,15 +921,7 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first,
|
||||
// utterly consistent with our firstname/lastname case.
|
||||
std::string userlower(first+"_"+last);
|
||||
LLStringUtil::toLower(userlower);
|
||||
mLindenUserDir = add(getOSUserAppDir(), userlower);
|
||||
|
||||
if (!grid.empty())
|
||||
{
|
||||
std::string gridlower(grid);
|
||||
LLStringUtil::toLower(gridlower);
|
||||
mLindenUserDir += "@";
|
||||
mLindenUserDir += gridlower;
|
||||
}
|
||||
mLindenUserDir = getGridSpecificDir(grid, add(getOSUserAppDir(), userlower));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -737,7 +958,7 @@ void LLDir::makePortable()
|
||||
initAppDirs(mAppName); // This is kinda lazy, but it's probably the quickest, most uniform way.
|
||||
}
|
||||
|
||||
void LLDir::setChatLogsDir(const std::string &path)
|
||||
void LLDir::setChatLogsDir( const std::string& path)
|
||||
{
|
||||
if (!path.empty() )
|
||||
{
|
||||
@@ -749,6 +970,11 @@ void LLDir::setChatLogsDir(const std::string &path)
|
||||
}
|
||||
}
|
||||
|
||||
void LLDir::updatePerAccountChatLogsDir(const std::string &grid)
|
||||
{
|
||||
mPerAccountChatLogsDir = getGridSpecificDir(grid, add(getChatLogsDir(), mUserName));
|
||||
}
|
||||
|
||||
void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last)
|
||||
{
|
||||
// if both first and last aren't set, assume we're grabbing the cached dir
|
||||
@@ -758,14 +984,9 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
|
||||
// utterly consistent with our firstname/lastname case.
|
||||
std::string userlower(first+"_"+last);
|
||||
LLStringUtil::toLower(userlower);
|
||||
mPerAccountChatLogsDir = add(getChatLogsDir(), userlower);
|
||||
if (!grid.empty())
|
||||
{
|
||||
std::string gridlower(grid);
|
||||
LLStringUtil::toLower(gridlower);
|
||||
mPerAccountChatLogsDir += "@";
|
||||
mPerAccountChatLogsDir += gridlower;
|
||||
}
|
||||
|
||||
mUserName = userlower;
|
||||
updatePerAccountChatLogsDir(grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -773,21 +994,59 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
|
||||
}
|
||||
}
|
||||
|
||||
void LLDir::setSkinFolder(const std::string &skin_folder)
|
||||
void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language)
|
||||
{
|
||||
mSkinDir = getSkinBaseDir();
|
||||
append(mSkinDir, skin_folder);
|
||||
LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'"
|
||||
<< LL_ENDL;
|
||||
mSkinName = skin_folder;
|
||||
mLanguage = language;
|
||||
|
||||
// user modifications to current skin
|
||||
// e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
|
||||
mUserSkinDir = getOSUserAppDir();
|
||||
append(mUserSkinDir, "skins_sg1");
|
||||
append(mUserSkinDir, skin_folder);
|
||||
// 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_sg1");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLDir::getSkinFolder() const
|
||||
{
|
||||
return mSkinName;
|
||||
}
|
||||
|
||||
std::string LLDir::getLanguage() const
|
||||
{
|
||||
return mLanguage;
|
||||
}
|
||||
|
||||
bool LLDir::setCacheDir(const std::string &path)
|
||||
|
||||
@@ -78,7 +78,7 @@ class LLDir
|
||||
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
|
||||
|
||||
virtual std::string getCurPath() = 0;
|
||||
virtual BOOL fileExists(const std::string &filename) const = 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;
|
||||
@@ -103,11 +103,13 @@ class LLDir
|
||||
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 &getSkinDir() const; // User-specified skin folder.
|
||||
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 &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;
|
||||
@@ -120,25 +122,80 @@ class LLDir
|
||||
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(), getSkinDir(), getDefaultSkinDir()
|
||||
std::string findSkinnedFilename(const std::string &filename) const;
|
||||
std::string findSkinnedFilename(const std::string &subdir, const std::string &filename) const;
|
||||
std::string findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
|
||||
// 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;
|
||||
|
||||
// For producing safe download file names from potentially unsafe ones
|
||||
static std::string getScrubbedFileName(const std::string uncleanFileName);
|
||||
static std::string getScrubbedFileName(const std::string& uncleanFileName);
|
||||
static std::string getForbiddenFileChars();
|
||||
static std::string getGridSpecificDir( const std::string& in, const std::string& grid );
|
||||
void setDumpDir( const std::string& path );
|
||||
|
||||
void makePortable();
|
||||
virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
|
||||
virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last); // Set the per user chat log directory.
|
||||
virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string& last); // Set the per user chat log directory.
|
||||
virtual void setLindenUserDir(const std::string& grid, const std::string& first, const std::string& last); // Set the linden user dir to this user's dir
|
||||
virtual void setSkinFolder(const std::string &skin_folder);
|
||||
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(const std::string &grid);
|
||||
|
||||
virtual void dumpCurrentDirectories();
|
||||
|
||||
@@ -156,6 +213,16 @@ 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);
|
||||
|
||||
// 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
|
||||
@@ -173,12 +240,21 @@ protected:
|
||||
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 mSkinDir; // Location for current skin info.
|
||||
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
|
||||
};
|
||||
|
||||
void dir_exists_or_crash(const std::string &dir_name);
|
||||
|
||||
@@ -257,7 +257,7 @@ std::string LLDir_Linux::getCurPath()
|
||||
}
|
||||
|
||||
|
||||
BOOL LLDir_Linux::fileExists(const std::string &filename) const
|
||||
bool LLDir_Linux::fileExists(const std::string &filename) const
|
||||
{
|
||||
struct stat stat_data;
|
||||
// Check the age of the file
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
|
||||
virtual std::string getCurPath();
|
||||
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
|
||||
/*virtual*/ BOOL fileExists(const std::string &filename) const;
|
||||
/*virtual*/ bool fileExists(const std::string &filename) const;
|
||||
|
||||
/*virtual*/ std::string getLLPluginLauncher();
|
||||
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
|
||||
|
||||
@@ -267,7 +267,7 @@ std::string LLDir_Mac::getCurPath()
|
||||
|
||||
|
||||
|
||||
BOOL LLDir_Mac::fileExists(const std::string &filename) const
|
||||
bool LLDir_Mac::fileExists(const std::string &filename) const
|
||||
{
|
||||
struct stat stat_data;
|
||||
// Check the age of the file
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
virtual std::string getCurPath();
|
||||
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
|
||||
virtual BOOL fileExists(const std::string &filename) const;
|
||||
virtual bool fileExists(const std::string &filename) const;
|
||||
|
||||
/*virtual*/ std::string getLLPluginLauncher();
|
||||
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
|
||||
|
||||
@@ -278,7 +278,7 @@ std::string LLDir_Solaris::getCurPath()
|
||||
}
|
||||
|
||||
|
||||
BOOL LLDir_Solaris::fileExists(const std::string &filename) const
|
||||
bool LLDir_Solaris::fileExists(const std::string &filename) const
|
||||
{
|
||||
struct stat stat_data;
|
||||
// Check the age of the file
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
|
||||
virtual std::string getCurPath();
|
||||
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
|
||||
/*virtual*/ BOOL fileExists(const std::string &filename) const;
|
||||
/*virtual*/ bool fileExists(const std::string &filename) const;
|
||||
|
||||
private:
|
||||
DIR *mDirp;
|
||||
|
||||
@@ -48,60 +48,28 @@ LLDir_Win32::LLDir_Win32()
|
||||
|
||||
WCHAR w_str[MAX_PATH];
|
||||
|
||||
HRESULT (WINAPI* pSHGetKnownFolderPath)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath) = NULL;
|
||||
HMODULE shell = LoadLibrary(L"shell32");
|
||||
if(shell) //SHGetSpecialFolderPath is deprecated from Vista an onwards. Try to use SHGetKnownFolderPath if it's available
|
||||
{
|
||||
pSHGetKnownFolderPath = (HRESULT (WINAPI *)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *))GetProcAddress(shell, "SHGetKnownFolderPath");
|
||||
}
|
||||
WCHAR* pPath = NULL;
|
||||
if(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK)
|
||||
wcscpy_s(w_str, pPath);
|
||||
|
||||
// Application Data is where user settings go
|
||||
if(pSHGetKnownFolderPath)
|
||||
{
|
||||
WCHAR* pPath = NULL;
|
||||
if((*pSHGetKnownFolderPath)(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK)
|
||||
wcscpy_s(w_str,pPath);
|
||||
else
|
||||
SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str );
|
||||
if(pPath)
|
||||
CoTaskMemFree(pPath);
|
||||
}
|
||||
else //XP doesn't support SHGetKnownFolderPath
|
||||
{
|
||||
SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str );
|
||||
}
|
||||
CoTaskMemFree(pPath);
|
||||
pPath = NULL;
|
||||
|
||||
mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));
|
||||
|
||||
// We want cache files to go on the local disk, even if the
|
||||
// user is on a network with a "roaming profile".
|
||||
//
|
||||
// On XP this is:
|
||||
// C:\Docments and Settings\James\Local Settings\Application Data
|
||||
// On Vista this is:
|
||||
// C:\Users\James\AppData\Local
|
||||
// On Vista and above this is:
|
||||
// C:\Users\<USERNAME>\AppData\Local
|
||||
//
|
||||
// We used to store the cache in AppData\Roaming, and the installer
|
||||
// cleans up that version on upgrade. JC
|
||||
if(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK)
|
||||
wcscpy_s(w_str, pPath);
|
||||
|
||||
|
||||
if(pSHGetKnownFolderPath)
|
||||
{
|
||||
WCHAR* pPath = NULL;
|
||||
if((*pSHGetKnownFolderPath)(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK)
|
||||
wcscpy_s(w_str,pPath);
|
||||
else
|
||||
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str );
|
||||
if(pPath)
|
||||
CoTaskMemFree(pPath);
|
||||
}
|
||||
else //XP doesn't support SHGetKnownFolderPath
|
||||
{
|
||||
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str );
|
||||
}
|
||||
|
||||
if(shell)
|
||||
FreeLibrary(shell);
|
||||
CoTaskMemFree(pPath);
|
||||
pPath = NULL;
|
||||
|
||||
mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));
|
||||
|
||||
@@ -288,7 +256,7 @@ std::string LLDir_Win32::getCurPath()
|
||||
}
|
||||
|
||||
|
||||
BOOL LLDir_Win32::fileExists(const std::string &filename) const
|
||||
bool LLDir_Win32::fileExists(const std::string &filename) const
|
||||
{
|
||||
llstat stat_data;
|
||||
// Check the age of the file
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
/*virtual*/ std::string getCurPath();
|
||||
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
|
||||
/*virtual*/ BOOL fileExists(const std::string &filename) const;
|
||||
/*virtual*/ bool fileExists(const std::string &filename) const;
|
||||
|
||||
/*virtual*/ std::string getLLPluginLauncher();
|
||||
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
|
||||
|
||||
@@ -49,7 +49,11 @@ private:
|
||||
LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
|
||||
: mIsValid(false)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
fs::path dir_path(utf8str_to_utf16str(dirname).c_str());
|
||||
#else
|
||||
fs::path dir_path(dirname);
|
||||
#endif
|
||||
|
||||
bool is_dir = false;
|
||||
|
||||
@@ -58,11 +62,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
|
||||
{
|
||||
is_dir = fs::is_directory(dir_path);
|
||||
}
|
||||
#if BOOST_FILESYSTEM_VERSION >= 3
|
||||
catch (fs::filesystem_error& e)
|
||||
#else
|
||||
catch (fs::basic_filesystem_error<fs::path>& e)
|
||||
#endif
|
||||
catch (const fs::filesystem_error& e)
|
||||
{
|
||||
LL_WARNS() << e.what() << LL_ENDL;
|
||||
return;
|
||||
@@ -79,13 +79,9 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
|
||||
{
|
||||
mIter = fs::directory_iterator(dir_path);
|
||||
}
|
||||
#if BOOST_FILESYSTEM_VERSION >= 3
|
||||
catch (fs::filesystem_error& e)
|
||||
#else
|
||||
catch (fs::basic_filesystem_error<fs::path>& e)
|
||||
#endif
|
||||
catch (const fs::filesystem_error& e)
|
||||
{
|
||||
LL_ERRS() << e.what() << LL_ENDL;
|
||||
LL_WARNS() << e.what() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,7 +97,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
|
||||
}
|
||||
catch (boost::regex_error& e)
|
||||
{
|
||||
LL_ERRS() << "\"" << exp << "\" is not a valid regular expression: "
|
||||
LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: "
|
||||
<< e.what() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
@@ -125,20 +121,26 @@ bool LLDirIterator::Impl::next(std::string &fname)
|
||||
|
||||
fs::directory_iterator end_itr; // default construction yields past-the-end
|
||||
bool found = false;
|
||||
while (mIter != end_itr && !found)
|
||||
{
|
||||
boost::smatch match;
|
||||
#if BOOST_FILESYSTEM_VERSION >= 3
|
||||
std::string name = mIter->path().filename().string();
|
||||
#else
|
||||
std::string name = mIter->path().filename();
|
||||
#endif
|
||||
if ((found = boost::regex_match(name, match, mFilterExp)))
|
||||
{
|
||||
fname = name;
|
||||
}
|
||||
|
||||
++mIter;
|
||||
// Check if path is a directory.
|
||||
try
|
||||
{
|
||||
while (mIter != end_itr && !found)
|
||||
{
|
||||
boost::smatch match;
|
||||
std::string name = mIter->path().filename().string();
|
||||
found = boost::regex_match(name, match, mFilterExp);
|
||||
if (found)
|
||||
{
|
||||
fname = name;
|
||||
}
|
||||
|
||||
++mIter;
|
||||
}
|
||||
}
|
||||
catch (const fs::filesystem_error& e)
|
||||
{
|
||||
LL_WARNS() << e.what() << LL_ENDL;
|
||||
}
|
||||
|
||||
return found;
|
||||
|
||||
Reference in New Issue
Block a user