From eb191e3590823c2d29655fe3aaa77102ca7672cd Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 15 Aug 2010 08:13:31 +0000 Subject: SWORD25: Fix loading files with relative paths. svn-id: r53246 --- engines/sword25/package/scummvmpackagemanager.cpp | 111 +++------------------- 1 file changed, 12 insertions(+), 99 deletions(-) diff --git a/engines/sword25/package/scummvmpackagemanager.cpp b/engines/sword25/package/scummvmpackagemanager.cpp index 9dafb45c08..d21054e28a 100644 --- a/engines/sword25/package/scummvmpackagemanager.cpp +++ b/engines/sword25/package/scummvmpackagemanager.cpp @@ -40,104 +40,17 @@ namespace Sword25 { const char PATH_SEPARATOR = '/'; -const char NAVIGATION_CHARACTER = '.'; -// ----------------------------------------------------------------------------- -// Support functions and classes -// ----------------------------------------------------------------------------- - -static Common::String RemoveRedundantPathSeparators(const Common::String &Path) { - Common::String Result; - - // Iterate over all the chracters of the input path - Common::String::const_iterator It = Path.begin(); - while (It != Path.end()) { - if (*It == PATH_SEPARATOR) { - // Directory separater found - - // Skip over directory separator(s) - while (It != Path.end() && *It == PATH_SEPARATOR) ++It; - - // Unless it's the end of the path, add the separator - if (It != Path.end()) Result += PATH_SEPARATOR; - } else { - // Normal characters are copied over unchanged - Result += *It; - ++It; - } - } - - return Result; -} - -// --------------------------------------------------------------------- - -static PathElementArray SeparatePath(const Common::String &Path, const Common::String &CurrentDirectory) { - // Determine whether the path is absolute (begins with /) or relative, in which case it's added - // to the current directory - Common::String wholePath = (Path.size() >= 1 && Path[0] == PATH_SEPARATOR) ? "" : CurrentDirectory + PATH_SEPARATOR; - - // Add in the provided path - wholePath += RemoveRedundantPathSeparators(Path); - - // Parse the path and divide into it's components. This ensures that occurences of ".." and "." - // are handled correctly. - PathElementArray pathElements; - size_t separatorPos = 0; - while (separatorPos < wholePath.size()) { - // Find next directory separator - const char *p = strchr(wholePath.c_str() + separatorPos + 1, PATH_SEPARATOR); - size_t nextseparatorPos = (p == NULL) ? wholePath.size() : p - wholePath.c_str(); - - // Calculate the beginning and end of the path element - Common::String::const_iterator elementBegin = wholePath.begin() + separatorPos + 1; - Common::String::const_iterator elementEnd = wholePath.begin() + nextseparatorPos; - - if (elementEnd - elementBegin == 2 && - elementBegin[0] == NAVIGATION_CHARACTER && - elementBegin[1] == NAVIGATION_CHARACTER) { - // element is "..", therefore the previous path element should be removed - if (pathElements.size()) pathElements.pop_back(); - } else if (elementEnd - elementBegin == 1 && - elementBegin[0] == NAVIGATION_CHARACTER) { - // element is ".", so we do nothing - } else { - // Normal elements get added to the list - pathElements.push_back(new PathElement(wholePath.begin() + separatorPos + 1, wholePath.begin() + nextseparatorPos)); - } +static Common::String normalizePath(const Common::String &path, const Common::String ¤tDirectory) { + Common::String wholePath = (path.size() >= 1 && path[0] == PATH_SEPARATOR) ? path : currentDirectory + PATH_SEPARATOR + path; - separatorPos = nextseparatorPos; - } - - return pathElements; -} - -static Common::String NormalizePath(const Common::String &Path, const Common::String &CurrentDirectory) { - // Get the path elements for the file - PathElementArray pathElements = SeparatePath(Path, CurrentDirectory); - - if (pathElements.size()) { - // The individual path elements are fitted together, separated by a directory - // separator. The resulting string is returned as a result - Common::String Result; - - PathElementArray::const_iterator It = pathElements.begin(); - while (It != pathElements.end()) { - Result += PATH_SEPARATOR; - Result += Common::String((*It)->GetBegin(), (*It)->GetEnd()); - ++It; - } - - return Result; - } else { + if (wholePath.size() == 0) { // The path list has no elements, therefore the root directory is returned return Common::String(PATH_SEPARATOR); } -} -// ----------------------------------------------------------------------------- -// Constructor / Destructor -// ----------------------------------------------------------------------------- + return Common::normalizePath(wholePath, PATH_SEPARATOR); +} BS_ScummVMPackageManager::BS_ScummVMPackageManager(BS_Kernel *KernelPtr) : BS_PackageManager(KernelPtr), @@ -222,7 +135,7 @@ bool BS_ScummVMPackageManager::LoadDirectoryAsPackage(const Common::String &Dire void *BS_ScummVMPackageManager::GetFile(const Common::String &FileName, unsigned int *FileSizePtr) { Common::SeekableReadStream *in; - Common::ArchiveMemberPtr fileNode = GetArchiveMember(FileName); + Common::ArchiveMemberPtr fileNode = GetArchiveMember(normalizePath(FileName, _currentDirectory)); if (!fileNode) return 0; if (!(in = fileNode->createReadStream())) @@ -250,23 +163,23 @@ Common::String BS_ScummVMPackageManager::GetCurrentDirectory() { // ----------------------------------------------------------------------------- -bool BS_ScummVMPackageManager::ChangeDirectory(const Common::String &Directory) { +bool BS_ScummVMPackageManager::ChangeDirectory(const Common::String &directory) { // Get the path elements for the file - _currentDirectory = NormalizePath(Directory, _currentDirectory); + _currentDirectory = normalizePath(directory, _currentDirectory); return true; } // ----------------------------------------------------------------------------- Common::String BS_ScummVMPackageManager::GetAbsolutePath(const Common::String &FileName) { - return NormalizePath(FileName, _currentDirectory); + return normalizePath(FileName, _currentDirectory); } // ----------------------------------------------------------------------------- unsigned int BS_ScummVMPackageManager::GetFileSize(const Common::String &FileName) { Common::SeekableReadStream *in; - Common::ArchiveMemberPtr fileNode = GetArchiveMember(FileName); + Common::ArchiveMemberPtr fileNode = GetArchiveMember(normalizePath(FileName, _currentDirectory)); if (!fileNode) return 0; if (!(in = fileNode->createReadStream())) @@ -289,7 +202,7 @@ unsigned int BS_ScummVMPackageManager::GetFileType(const Common::String &FileNam // ----------------------------------------------------------------------------- bool BS_ScummVMPackageManager::FileExists(const Common::String &FileName) { - Common::ArchiveMemberPtr fileNode = GetArchiveMember(FileName); + Common::ArchiveMemberPtr fileNode = GetArchiveMember(normalizePath(FileName, _currentDirectory)); return fileNode; } @@ -333,7 +246,7 @@ public: BS_PackageManager::FileSearch *BS_ScummVMPackageManager::CreateSearch( const Common::String &Filter, const Common::String &Path, unsigned int TypeFilter) { #if 0 - Common::String NormalizedPath = NormalizePath(Path, _currentDirectory); + Common::String NormalizedPath = normalizePath(Path, _currentDirectory); Common::FSNode folderNode = GetFSNode(Path); if (!folderNode.exists() || !folderNode.isDirectory()) return NULL; -- cgit v1.2.3