/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "hsUtils.h" #include "hsFiles.h" #include "plStreamSource.h" #include "plSecureStream.h" #include "plEncryptedStream.h" #include "plFileUtils.h" void ToLower(std::wstring& str) { for (unsigned i = 0; i < str.length(); i++) str[i] = towlower(str[i]); } void ReplaceSlashes(std::wstring& path, wchar replaceWith) { for (unsigned i = 0; i < path.length(); i++) { if ((path[i] == L'\\') || (path[i] == L'/')) path[i] = replaceWith; } } void plStreamSource::ICleanup() { // loop through all the file data records, and delete the streams std::map::iterator curData; for (curData = fFileData.begin(); curData != fFileData.end(); curData++) { curData->second.fStream->Close(); delete curData->second.fStream; curData->second.fStream = nil; } fFileData.clear(); } void plStreamSource::IBreakupFilename(std::wstring filename, std::wstring& dir, std::wstring& ext) { // break the filename up into its parts char* temp = hsWStringToString(filename.c_str()); std::string sFilename = temp; std::string sExt = plFileUtils::GetFileExt(temp); plFileUtils::StripFile(temp); std::string sDir = temp; delete [] temp; if (sDir == sFilename) // no directory sDir = ""; if (sDir != "") if ((sDir[sDir.length()-1] == '/') || (sDir[sDir.length()-1] == '\\')) sDir = sDir.substr(0, sDir.length() - 1); // trim the slash, if it has one wchar_t* wTemp; wTemp = hsStringToWString(sDir.c_str()); dir = wTemp; delete [] wTemp; wTemp = hsStringToWString(sExt.c_str()); ext = wTemp; delete [] wTemp; } hsStream* plStreamSource::GetFile(std::wstring filename) { ToLower(filename); ReplaceSlashes(filename, L'/'); if (fFileData.find(filename) == fFileData.end()) { #ifndef PLASMA_EXTERNAL_RELEASE // internal releases can pull from disk char* temp = hsWStringToString(filename.c_str()); std::string sFilename = temp; delete [] temp; if (plFileUtils::FileExists(sFilename.c_str())) { // file exists on disk, cache it std::wstring dir, ext; IBreakupFilename(filename, dir, ext); fFileData[filename].fFilename = filename; fFileData[filename].fDir = dir; fFileData[filename].fExt = ext; if (plSecureStream::IsSecureFile(sFilename.c_str())) { UInt32 encryptionKey[4]; plFileUtils::GetSecureEncryptionKey(sFilename.c_str(), encryptionKey, 4); fFileData[filename].fStream = plSecureStream::OpenSecureFile(sFilename.c_str(), 0, encryptionKey); } else // otherwise it is an encrypted or plain stream, this call handles both fFileData[filename].fStream = plEncryptedStream::OpenEncryptedFile(sFilename.c_str()); return fFileData[filename].fStream; } #endif // PLASMA_EXTERNAL_RELEASE return nil; } return fFileData[filename].fStream; } std::vector plStreamSource::GetListOfNames(std::wstring dir, std::wstring ext) { ToLower(ext); ToLower(dir); ReplaceSlashes(dir, L'/'); if (ext[0] == L'.') ext = ext.substr(1, ext.length()); // trim the dot, if it has one if (dir != L"") if ((dir[dir.length()-1] == L'/') || (dir[dir.length()-1] == L'\\')) dir = dir.substr(0, dir.length() - 1); // trim the slash, if it has one // loop through all the file data records, and create the list std::vector retVal; std::map::iterator curData; for (curData = fFileData.begin(); curData != fFileData.end(); curData++) { if ((curData->second.fDir == dir.c_str()) && (curData->second.fExt == ext)) retVal.push_back(curData->second.fFilename); } #ifndef PLASMA_EXTERNAL_RELEASE // in internal releases, we can use on-disk files if they exist // Build the search string as "dir/*.ext" std::wstring wSearchStr = dir + L"/*." + ext; char* temp = hsWStringToString(wSearchStr.c_str()); std::string searchStr = temp; delete [] temp; hsFolderIterator folderIter(searchStr.c_str(), true); while (folderIter.NextFile()) { const char* filename = folderIter.GetFileName(); wchar_t* wTemp = hsStringToWString(filename); std::wstring wFilename = dir + L"/" + wTemp; delete [] wTemp; ToLower(wFilename); if (fFileData.find(wFilename) == fFileData.end()) // we haven't added it yet retVal.push_back(wFilename); } #endif // PLASMA_EXTERNAL_RELEASE return retVal; } bool plStreamSource::InsertFile(std::wstring filename, hsStream* stream) { ToLower(filename); ReplaceSlashes(filename, L'/'); if (fFileData.find(filename) != fFileData.end()) return false; // duplicate entry, return failure // break the filename up into its parts std::wstring dir, ext; IBreakupFilename(filename, dir, ext); // copy the data over (takes ownership of the stream!) fFileData[filename].fFilename = filename; fFileData[filename].fDir = dir; fFileData[filename].fExt = ext; fFileData[filename].fStream = stream; return true; } plStreamSource* plStreamSource::GetInstance() { static plStreamSource source; return &source; }