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.

196 lines
5.9 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/>.
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<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 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<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;
}