You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
7.3 KiB
222 lines
7.3 KiB
/*==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 <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
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 <string> |
|
#include "hsFiles.h" |
|
#include "plStreamSource.h" |
|
#include "plSecureStream.h" |
|
#include "plEncryptedStream.h" |
|
#include "plFileUtils.h" |
|
|
|
#if HS_BUILD_FOR_UNIX |
|
# include <wctype.h> |
|
#endif |
|
|
|
void ToLower(std::wstring& str) |
|
{ |
|
for (unsigned i = 0; i < str.length(); i++) |
|
str[i] = towlower(str[i]); |
|
} |
|
|
|
void ReplaceSlashes(std::wstring& path, wchar_t 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<std::wstring, fileData>::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_t encryptionKey[4]; |
|
if (!plSecureStream::GetSecureEncryptionKey(sFilename.c_str(), encryptionKey, 4)) |
|
{ |
|
FATAL("Hey camper... You need an NTD key file!"); |
|
return nil; |
|
} |
|
|
|
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<std::wstring> 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<std::wstring> retVal; |
|
std::map<std::wstring, fileData>::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; |
|
}
|
|
|