mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
CWE Directory Reorganization
Rearrange directory structure of CWE to be loosely equivalent to the H'uru Plasma repository. Part 1: Movement of directories and files.
This commit is contained in:
184
Sources/Plasma/PubUtilLib/plFile/hsFiles.cpp
Normal file
184
Sources/Plasma/PubUtilLib/plFile/hsFiles.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/*==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 "hsFiles.h"
|
||||
#include <string.h>
|
||||
#include "hsUtils.h"
|
||||
|
||||
#include "hsExceptions.h"
|
||||
|
||||
#if HS_BUILD_FOR_MAC
|
||||
#define kDirChar ':'
|
||||
#elif HS_BUILD_FOR_WIN32
|
||||
#define kDirChar '\\'
|
||||
#else
|
||||
#define kDirChar '/'
|
||||
#endif
|
||||
|
||||
|
||||
static const char* FindNameInPath(const char path[])
|
||||
{
|
||||
const char* name = ::strrchr(path, kDirChar);
|
||||
|
||||
if (name == nil)
|
||||
name = path;
|
||||
return name;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
#if !HS_BUILD_FOR_PS2
|
||||
|
||||
hsFile::hsFile() : fPathAndName(nil), fFILE(nil)
|
||||
{
|
||||
}
|
||||
|
||||
hsFile::hsFile(const char pathAndName[]) : fPathAndName(nil), fFILE(nil)
|
||||
{
|
||||
if (pathAndName)
|
||||
fPathAndName = hsStrcpy(pathAndName);
|
||||
}
|
||||
|
||||
hsFile::~hsFile()
|
||||
{
|
||||
this->SetPathAndName(nil);
|
||||
}
|
||||
|
||||
const char* hsFile::GetPathAndName()
|
||||
{
|
||||
return fPathAndName;
|
||||
}
|
||||
|
||||
void hsFile::SetPathAndName(const char pathAndName[])
|
||||
{
|
||||
this->Close();
|
||||
|
||||
if (fPathAndName)
|
||||
{ delete[] fPathAndName;
|
||||
fPathAndName = nil;
|
||||
}
|
||||
if (pathAndName)
|
||||
fPathAndName = hsStrcpy(pathAndName);
|
||||
}
|
||||
|
||||
const char* hsFile::GetName()
|
||||
{
|
||||
return FindNameInPath(this->GetPathAndName());
|
||||
}
|
||||
|
||||
FILE* hsFile::OpenFILE(const char mode[], hsBool throwIfFailure)
|
||||
{
|
||||
this->Close();
|
||||
|
||||
// We call the virtual method here rather than using
|
||||
// fPathAndName directly, allowing a subclass to construct
|
||||
// the name if necessary
|
||||
//
|
||||
const char* name = this->GetPathAndName();
|
||||
if (name)
|
||||
fFILE = ::fopen(name, mode);
|
||||
|
||||
hsThrowIfTrue(throwIfFailure && fFILE == nil);
|
||||
return fFILE;
|
||||
}
|
||||
|
||||
hsStream* hsFile::OpenStream(const char mode[], hsBool throwIfFailure)
|
||||
{
|
||||
FILE* file = this->OpenFILE(mode, throwIfFailure);
|
||||
|
||||
if (file)
|
||||
{ hsUNIXStream* stream = TRACKED_NEW hsUNIXStream;
|
||||
stream->SetFILE(file);
|
||||
return stream;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
void hsFile::Close()
|
||||
{
|
||||
if (fFILE)
|
||||
{ int err = ::fflush(fFILE);
|
||||
hsIfDebugMessage(err != 0, "fflush failed", err);
|
||||
err = ::fclose(fFILE);
|
||||
hsIfDebugMessage(err != 0, "fclose failed", err);
|
||||
fFILE = nil;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool hsFolderIterator::NextFileSuffix(const char suffix[])
|
||||
{
|
||||
while (this->NextFile())
|
||||
{ const char* fileSuffix = ::strrchr(this->GetFileName(), '.');
|
||||
if (fileSuffix != nil && ::_stricmp(fileSuffix, suffix) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int hsFolderIterator::GetPathAndName(char pathandname[])
|
||||
{
|
||||
const char* name = this->GetFileName();
|
||||
int pathLen = hsStrlen(fPath);
|
||||
|
||||
// add 1 for null terminator
|
||||
int totalLen = pathLen + sizeof(kDirChar) + hsStrlen(name) + 1;
|
||||
hsAssert(totalLen <= kFolderIterator_MaxPath, "Overrun kFolderIterator_MaxPath");
|
||||
|
||||
if (pathandname)
|
||||
{ hsStrcpy(pathandname, fPath);
|
||||
if (pathLen > 0 && pathandname[pathLen - 1] != kDirChar)
|
||||
pathandname[pathLen++] = kDirChar;
|
||||
hsStrcpy(pathandname + pathLen, name);
|
||||
}
|
||||
return totalLen;
|
||||
}
|
||||
|
||||
FILE* hsFolderIterator::OpenFILE(const char mode[])
|
||||
{
|
||||
char fileName[kFolderIterator_MaxPath];
|
||||
|
||||
(void)this->GetPathAndName(fileName);
|
||||
|
||||
return ::fopen(fileName, mode);
|
||||
}
|
||||
|
204
Sources/Plasma/PubUtilLib/plFile/hsFiles.h
Normal file
204
Sources/Plasma/PubUtilLib/plFile/hsFiles.h
Normal file
@ -0,0 +1,204 @@
|
||||
/*==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==*/
|
||||
#ifndef hsFiles_Defined
|
||||
#define hsFiles_Defined
|
||||
|
||||
#include "hsStream.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if HS_BUILD_FOR_UNIX
|
||||
#include <limits.h>
|
||||
#define kFolderIterator_MaxPath PATH_MAX
|
||||
#include <unistd.h>
|
||||
#define SetCurrentDirectory chdir
|
||||
#elif !HS_BUILD_FOR_PS2
|
||||
#define kFolderIterator_MaxPath _MAX_PATH
|
||||
#else
|
||||
#define kFolderIterator_MaxPath 255
|
||||
#endif
|
||||
|
||||
#if HS_BUILD_FOR_MAC
|
||||
#include <Files.h>
|
||||
#include <Script.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
# define PATH_SEPARATOR '\\'
|
||||
# define WPATH_SEPARATOR L'\\'
|
||||
# define PATH_SEPARATOR_STR "\\"
|
||||
# define WPATH_SEPARATOR_STR L"\\"
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
# define PATH_SEPARATOR '/'
|
||||
# define WPATH_SEPARATOR L'/'
|
||||
# define PATH_SEPARATOR_STR "/"
|
||||
# define WPATH_SEPARATOR_STR L"/"
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
#if !HS_BUILD_FOR_PS2
|
||||
|
||||
class hsFile {
|
||||
hsFile& operator=(const hsFile&); // disallow assignment
|
||||
protected:
|
||||
char* fPathAndName;
|
||||
FILE* fFILE;
|
||||
public:
|
||||
hsFile();
|
||||
hsFile(const char pathAndName[]);
|
||||
virtual ~hsFile();
|
||||
|
||||
const char* GetName();
|
||||
virtual const char* GetPathAndName();
|
||||
virtual void SetPathAndName(const char pathAndName[]);
|
||||
|
||||
virtual FILE* OpenFILE(const char mode[], hsBool throwIfFailure = false);
|
||||
virtual hsStream* OpenStream(const char mode[], hsBool throwIfFailure = false);
|
||||
|
||||
virtual void Close(); // called automatically in the destructor
|
||||
};
|
||||
typedef hsFile hsUnixFile; // for compatibility
|
||||
|
||||
#if HS_BUILD_FOR_MAC
|
||||
class hsMacFile : public hsFile {
|
||||
enum {
|
||||
kRefNum_Dirty,
|
||||
kPathName_Dirty
|
||||
};
|
||||
FSSpec fSpec;
|
||||
Int16 fRefNum;
|
||||
UInt16 fFlags;
|
||||
|
||||
void SetSpecFromName();
|
||||
void SetNameFromSpec();
|
||||
public:
|
||||
hsMacFile();
|
||||
hsMacFile(const FSSpec* spec);
|
||||
hsMacFile(const char pathAndName[]);
|
||||
virtual ~hsMacFile();
|
||||
|
||||
const FSSpec* GetSpec() const { return &fSpec; }
|
||||
void SetSpec(const FSSpec* spec);
|
||||
hsBool Create(OSType creator, OSType fileType, ScriptCode scriptCode = smSystemScript);
|
||||
hsBool OpenDataFork(SInt8 permission, Int16* refnum);
|
||||
|
||||
// Overrides
|
||||
virtual const char* GetPathAndName();
|
||||
virtual void SetPathAndName(const char pathAndName[]);
|
||||
virtual hsStream* OpenStream(const char mode[], hsBool throwIfFailure = false);
|
||||
virtual void Close();
|
||||
};
|
||||
typedef hsMacFile hsOSFile;
|
||||
#else
|
||||
typedef hsFile hsOSFile;
|
||||
#endif
|
||||
#endif // HS_BUILD_FOR_PS2
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class hsFolderIterator {
|
||||
char fPath[kFolderIterator_MaxPath];
|
||||
struct hsFolderIterator_Data* fData;
|
||||
bool fCustomFilter;
|
||||
public:
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
hsFolderIterator(const char path[] = nil, bool useCustomFilter=false);
|
||||
#else
|
||||
hsFolderIterator(const char path[] = nil, bool unused=true);
|
||||
hsFolderIterator(const struct FSSpec* spec); // Alt constructor
|
||||
#endif
|
||||
virtual ~hsFolderIterator();
|
||||
|
||||
const char* GetPath() const { return fPath; }
|
||||
void SetPath(const char path[]);
|
||||
|
||||
void Reset();
|
||||
hsBool NextFile();
|
||||
hsBool NextFileSuffix(const char suffix[]);
|
||||
const char* GetFileName() const;
|
||||
int GetPathAndName(char pathandname[] = nil);
|
||||
hsBool IsDirectory( void ) const;
|
||||
|
||||
FILE* OpenFILE(const char mode[]);
|
||||
|
||||
#if HS_BUILD_FOR_MAC
|
||||
void SetMacFolder(const char path[]);
|
||||
void SetMacFolder(OSType folderType);
|
||||
void SetMacFolder(Int16 vRefNum, Int32 dirID);
|
||||
hsBool NextMacFile(OSType targetFileType, OSType targetCreator);
|
||||
const struct FSSpec* GetMacSpec() const;
|
||||
OSType GetMacFileType() const;
|
||||
OSType GetMacCreator() const;
|
||||
#elif HS_BUILD_FOR_WIN32
|
||||
void SetWinSystemDir(const char subdir[]); // e.g. "Fonts"
|
||||
void SetFileFilterStr(const char filterStr[]); // e.g. "*.*"
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
// only implemented on Win32 for now
|
||||
class hsWFolderIterator {
|
||||
wchar fPath[kFolderIterator_MaxPath];
|
||||
struct hsWFolderIterator_Data* fData;
|
||||
bool fCustomFilter;
|
||||
public:
|
||||
hsWFolderIterator(const wchar path[] = nil, bool useCustomFilter=false);
|
||||
virtual ~hsWFolderIterator();
|
||||
|
||||
const wchar* GetPath() const { return fPath; }
|
||||
void SetPath(const wchar path[]);
|
||||
|
||||
void Reset();
|
||||
hsBool NextFile();
|
||||
hsBool NextFileSuffix(const wchar suffix[]);
|
||||
const wchar* GetFileName() const;
|
||||
int GetPathAndName(wchar pathandname[] = nil);
|
||||
hsBool IsDirectory( void ) const;
|
||||
|
||||
FILE* OpenFILE(const wchar mode[]);
|
||||
|
||||
void SetWinSystemDir(const wchar subdir[]); // e.g. "Fonts"
|
||||
void SetFileFilterStr(const wchar filterStr[]); // e.g. "*.*"
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
409
Sources/Plasma/PubUtilLib/plFile/hsFiles_Mac.cpp
Normal file
409
Sources/Plasma/PubUtilLib/plFile/hsFiles_Mac.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
/*==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 "hsFiles.h"
|
||||
#include "hsUtils.h"
|
||||
#include "hsMemory.h"
|
||||
|
||||
#if HS_BUILD_FOR_MAC
|
||||
|
||||
#include <Files.h>
|
||||
#include <Folders.h>
|
||||
#include <Errors.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
hsMacFile::hsMacFile() : fFlags(kRefNum_Dirty)
|
||||
{
|
||||
fSpec.name[0] = 0;
|
||||
}
|
||||
|
||||
hsMacFile::hsMacFile(const char pathAndName[]) : hsFile(pathAndName), fFlags(kRefNum_Dirty)
|
||||
{
|
||||
this->SetSpecFromName();
|
||||
}
|
||||
|
||||
hsMacFile::hsMacFile(const FSSpec* spec) : fFlags(kRefNum_Dirty)
|
||||
{
|
||||
this->SetSpec(spec);
|
||||
}
|
||||
|
||||
hsMacFile::~hsMacFile()
|
||||
{
|
||||
this->Close();
|
||||
}
|
||||
|
||||
void hsMacFile::SetSpec(const FSSpec* spec)
|
||||
{
|
||||
if (spec)
|
||||
fSpec = *spec;
|
||||
else
|
||||
fSpec.name[0] = 0;
|
||||
fFlags |= kPathName_Dirty;
|
||||
}
|
||||
|
||||
void hsMacFile::SetSpecFromName()
|
||||
{
|
||||
Str255 pstr;
|
||||
|
||||
if (fPathAndName == nil)
|
||||
fSpec.name[0] = 0;
|
||||
else
|
||||
{ hsC2PString(fPathAndName, pstr);
|
||||
::FSMakeFSSpec(0, 0, pstr, &fSpec);
|
||||
}
|
||||
}
|
||||
|
||||
void hsMacFile::SetNameFromSpec()
|
||||
{
|
||||
CInfoPBRec pb;
|
||||
Str255 dirNameP;
|
||||
char dirName[256], temp[256];
|
||||
int err;
|
||||
|
||||
hsP2CString(fSpec.name, temp);
|
||||
|
||||
pb.dirInfo.ioNamePtr = dirNameP;
|
||||
pb.dirInfo.ioVRefNum = fSpec.vRefNum;
|
||||
pb.dirInfo.ioDrParID = fSpec.parID;
|
||||
pb.dirInfo.ioFDirIndex = -1;
|
||||
|
||||
do {
|
||||
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
|
||||
err = PBGetCatInfoSync(&pb);
|
||||
hsThrowIfOSErr(err);
|
||||
|
||||
hsP2CString(dirNameP, dirName);
|
||||
strcat(dirName,":");
|
||||
strcat(dirName, temp);
|
||||
strcpy(temp, dirName);
|
||||
} while( pb.dirInfo.ioDrDirID != fsRtDirID);
|
||||
|
||||
hsAssert(fPathAndName == nil, "pathname should be nil");
|
||||
fPathAndName = hsStrcpy(temp);
|
||||
}
|
||||
|
||||
hsBool hsMacFile::Create(OSType creator, OSType fileType, ScriptCode scriptCode)
|
||||
{
|
||||
this->Close();
|
||||
|
||||
OSErr err;
|
||||
|
||||
(void)::FSpDelete(&fSpec);
|
||||
err = ::FSpCreate(&fSpec, creator, fileType, scriptCode);
|
||||
hsIfDebugMessage(err != 0, "FSpCreate failed", err);
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
#define kFileNotFound_Err -43
|
||||
|
||||
hsBool hsMacFile::OpenDataFork(SInt8 perm, Int16* refnum)
|
||||
{
|
||||
this->Close();
|
||||
|
||||
OSErr err;
|
||||
|
||||
err = ::FSpOpenDF(&fSpec, perm, &fRefNum);
|
||||
if (err == kFileNotFound_Err && (perm & fsWrPerm) && (perm & fsRdPerm) == 0)
|
||||
{ if (this->Create('HdSp', '????'))
|
||||
err = ::FSpOpenDF(&fSpec, perm, &fRefNum);
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
{ fFlags &= ~kRefNum_Dirty;
|
||||
if (refnum)
|
||||
*refnum = fRefNum;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* hsMacFile::GetPathAndName()
|
||||
{
|
||||
if (fFlags & kPathName_Dirty)
|
||||
{ this->SetNameFromSpec();
|
||||
fFlags &= ~kPathName_Dirty;
|
||||
}
|
||||
return fPathAndName;
|
||||
}
|
||||
|
||||
void hsMacFile::SetPathAndName(const char pathAndName[])
|
||||
{
|
||||
this->hsFile::SetPathAndName(pathAndName);
|
||||
this->SetSpecFromName();
|
||||
}
|
||||
|
||||
hsStream* hsMacFile::OpenStream(const char mode[], hsBool throwIfFailure)
|
||||
{
|
||||
hsThrowIfNilParam(mode);
|
||||
|
||||
short refnum;
|
||||
SInt8 perm = 0;
|
||||
|
||||
if (::strchr(mode, 'r'))
|
||||
perm |= fsRdPerm;
|
||||
if (::strchr(mode, 'w'))
|
||||
perm |= fsWrPerm;
|
||||
|
||||
if (this->OpenDataFork(perm, &refnum))
|
||||
{ hsFileStream* stream = TRACKED_NEW hsFileStream;
|
||||
stream->SetFileRef(refnum);
|
||||
return stream;
|
||||
}
|
||||
|
||||
hsThrowIfTrue(throwIfFailure);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void hsMacFile::Close()
|
||||
{
|
||||
if (fFlags & kRefNum_Dirty)
|
||||
{ OSErr err = ::FSClose(fRefNum);
|
||||
hsIfDebugMessage(err != 0, "FSClose failed", err);
|
||||
fFlags &= ~kRefNum_Dirty;
|
||||
}
|
||||
this->hsFile::Close();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct hsFolderIterator_Data {
|
||||
FSSpec fSpec;
|
||||
OSType fFileType;
|
||||
OSType fCreator;
|
||||
char fCName[_MAX_PATH];
|
||||
Int16 fCurrIndex;
|
||||
hsBool fValid;
|
||||
};
|
||||
|
||||
hsFolderIterator::hsFolderIterator(const char path[])
|
||||
{
|
||||
fData = TRACKED_NEW hsFolderIterator_Data;
|
||||
|
||||
fData->fCurrIndex = 0;
|
||||
fData->fValid = false;
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
this->SetPath(path);
|
||||
#else
|
||||
this->SetMacFolder(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
hsFolderIterator::hsFolderIterator(const struct FSSpec* spec) // Alt Constructor - pass in FSSpec from OpenDlg()
|
||||
{
|
||||
fData = TRACKED_NEW hsFolderIterator_Data;
|
||||
|
||||
fData->fCurrIndex = 0;
|
||||
fData->fValid = false;
|
||||
|
||||
SetMacFolder(spec->vRefNum, spec->parID);
|
||||
}
|
||||
|
||||
hsFolderIterator::~hsFolderIterator()
|
||||
{
|
||||
delete fData;
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetPath(const char path[])
|
||||
{
|
||||
fPath[0] = 0;
|
||||
fData->fValid = false;
|
||||
fData->fCurrIndex = 0;
|
||||
|
||||
if (path)
|
||||
{
|
||||
::strcpy(fPath, path);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void hsFolderIterator::SetMacFolder(OSType folderType)
|
||||
{
|
||||
fData->fCurrIndex = 0;
|
||||
fData->fValid = ::FindFolder(kOnSystemDisk, folderType, false,
|
||||
&fData->fSpec.vRefNum, &fData->fSpec.parID) == 0;
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetMacFolder(Int16 vRefNum, Int32 dirID)
|
||||
{
|
||||
fData->fSpec.vRefNum = vRefNum;
|
||||
fData->fSpec.parID = dirID;
|
||||
fData->fCurrIndex = 0;
|
||||
fData->fValid = true;
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetMacFolder(const char path[])
|
||||
{
|
||||
char tmp[255];
|
||||
FSSpec fileSpec;
|
||||
OSErr err;
|
||||
|
||||
hsCPathToMacPath(&tmp[1], (char*)path);
|
||||
tmp[0] = hsStrlen(&tmp[1]);
|
||||
SetPath((char*)&tmp[1]);
|
||||
|
||||
err = FSMakeFSSpec(0, 0, (const unsigned char*)tmp, &fileSpec);
|
||||
if(err == fnfErr)
|
||||
{
|
||||
HSDebugProc("XCmd directory does not exist.");
|
||||
return;
|
||||
}
|
||||
hsAssert(err == noErr, "Error making file spec.");
|
||||
|
||||
// by now we should have the file spec for the given
|
||||
// directory, however, the DirID is the PARENT directory,
|
||||
// not the child directory. The following steps should
|
||||
// give us the items we want.
|
||||
|
||||
CInfoPBRec pb;
|
||||
pb.hFileInfo.ioVRefNum = fileSpec.vRefNum;
|
||||
pb.hFileInfo.ioNamePtr = (StringPtr)fileSpec.name; // The name of the child directory.
|
||||
pb.hFileInfo.ioDirID = fileSpec.parID; // The ID of the parent directory.
|
||||
pb.hFileInfo.ioFDirIndex = 0;
|
||||
pb.hFileInfo.ioCompletion = 0;
|
||||
|
||||
err = ::PBGetCatInfoSync(&pb);
|
||||
hsAssert(err == noErr, "PBGetCatInfoSync() failure.");
|
||||
|
||||
fData->fSpec.vRefNum = fileSpec.vRefNum; // Volume reference
|
||||
fData->fSpec.parID = pb.dirInfo.ioDrDirID; // child directory ID (Finally!)
|
||||
fData->fCurrIndex = 0;
|
||||
fData->fValid = true;
|
||||
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void hsFolderIterator::Reset()
|
||||
{
|
||||
if (fData->fValid)
|
||||
fData->fCurrIndex = 1;
|
||||
#ifdef HS_DEBUGGING
|
||||
else
|
||||
hsAssert(fData->fCurrIndex == 0, "bad currindex");
|
||||
#endif
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::NextFile()
|
||||
{
|
||||
if (fData->fCurrIndex == 0)
|
||||
return false;
|
||||
|
||||
CInfoPBRec pb;
|
||||
|
||||
do {
|
||||
pb.hFileInfo.ioVRefNum = fData->fSpec.vRefNum;
|
||||
pb.hFileInfo.ioNamePtr = (StringPtr)fData->fSpec.name;
|
||||
pb.hFileInfo.ioDirID = fData->fSpec.parID;
|
||||
pb.hFileInfo.ioFDirIndex = fData->fCurrIndex++;
|
||||
|
||||
OSErr err = ::PBGetCatInfoSync(&pb);
|
||||
if (err)
|
||||
{
|
||||
fData->fCurrIndex = 0;
|
||||
return false;
|
||||
}
|
||||
} while (pb.hFileInfo.ioFlAttrib & ioDirMask);
|
||||
|
||||
fData->fFileType = pb.hFileInfo.ioFlFndrInfo.fdType;
|
||||
fData->fCreator = pb.hFileInfo.ioFlFndrInfo.fdCreator;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* hsFolderIterator::GetFileName() const
|
||||
{
|
||||
if (fData->fCurrIndex == 0)
|
||||
throw "end of folder";
|
||||
|
||||
// Copy our filename (in pascal format) into a cstring and then return
|
||||
HSMemory::BlockMove(&fData->fSpec.name[1], fData->fCName, fData->fSpec.name[0]);
|
||||
fData->fCName[fData->fSpec.name[0]] = 0;
|
||||
return fData->fCName;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool hsFolderIterator::NextMacFile(OSType targetFileType, OSType targetCreator)
|
||||
{
|
||||
for (;;)
|
||||
{ if (this->NextFile() == false)
|
||||
return false;
|
||||
if ((targetFileType == 0 || targetFileType == this->GetMacFileType()) &&
|
||||
(targetCreator == 0 || targetCreator == this->GetMacCreator()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const FSSpec* hsFolderIterator::GetMacSpec() const
|
||||
{
|
||||
if (fData->fCurrIndex == 0)
|
||||
throw "end of folder";
|
||||
return &fData->fSpec;
|
||||
}
|
||||
|
||||
|
||||
OSType hsFolderIterator::GetMacFileType() const
|
||||
{
|
||||
if (fData->fCurrIndex == 0)
|
||||
throw "end of folder";
|
||||
return fData->fFileType;
|
||||
}
|
||||
|
||||
OSType hsFolderIterator::GetMacCreator() const
|
||||
{
|
||||
if (fData->fCurrIndex == 0)
|
||||
throw "end of folder";
|
||||
return fData->fCreator;
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::IsDirectory( void ) const
|
||||
{
|
||||
hsAssert( false, "hsFolderIterator::IsDirectory() not defined on this platform!!!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // HS_BUILD_FOR_MAC
|
84
Sources/Plasma/PubUtilLib/plFile/hsFiles_PS2.cpp
Normal file
84
Sources/Plasma/PubUtilLib/plFile/hsFiles_PS2.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*==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 "hsFiles.h"
|
||||
|
||||
#if HS_BUILD_FOR_PS2
|
||||
|
||||
|
||||
|
||||
hsFolderIterator::hsFolderIterator(const char path[])
|
||||
{
|
||||
hsAssert(0,"No folder Interator defined for PS2 -- yet");
|
||||
}
|
||||
|
||||
hsFolderIterator::~hsFolderIterator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetPath(const char path[])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void hsFolderIterator::Reset()
|
||||
{
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::NextFile()
|
||||
{
|
||||
}
|
||||
|
||||
const char* hsFolderIterator::GetFileName() const
|
||||
{
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::IsDirectory( void ) const
|
||||
{
|
||||
hsAssert( false, "hsFolderIterator::IsDirectory() not defined on this platform!!!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // HS_BUILD_FOR_PS2
|
146
Sources/Plasma/PubUtilLib/plFile/hsFiles_Unix.cpp
Normal file
146
Sources/Plasma/PubUtilLib/plFile/hsFiles_Unix.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*==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 "hsFiles.h"
|
||||
|
||||
#if HS_BUILD_FOR_UNIX
|
||||
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <glob.h>
|
||||
#include "hsTemplates.h"
|
||||
#include "plFileUtils.h"
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
struct hsFolderIterator_Data {
|
||||
glob_t fGlobBuf;
|
||||
bool fInited;
|
||||
int fCnt;
|
||||
hsFolderIterator_Data() : fInited(false), fCnt(0) {}
|
||||
// ~hsFolderIterator_Data() { fInited=false; globfree(&fData->fGlobBuf); }
|
||||
};
|
||||
|
||||
hsFolderIterator::hsFolderIterator(const char path[], bool)
|
||||
{
|
||||
fData = TRACKED_NEW hsFolderIterator_Data;
|
||||
|
||||
this->SetPath(path);
|
||||
}
|
||||
|
||||
hsFolderIterator::~hsFolderIterator()
|
||||
{
|
||||
this->Reset();
|
||||
delete fData;
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetPath(const char path[])
|
||||
{
|
||||
fPath[0] = 0;
|
||||
if (path)
|
||||
{
|
||||
::strcpy(fPath, path);
|
||||
}
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
void hsFolderIterator::Reset()
|
||||
{
|
||||
if (fData->fInited)
|
||||
{
|
||||
globfree(&fData->fGlobBuf);
|
||||
fData->fCnt = 0;
|
||||
fData->fInited=false;
|
||||
}
|
||||
}
|
||||
hsBool hsFolderIterator::NextFile()
|
||||
{
|
||||
if (fData->fInited == false)
|
||||
{
|
||||
std::string path=fPath;
|
||||
if(!(strchr(fPath,'*') || strchr(fPath,'?') || strchr(fPath,'[')))
|
||||
{
|
||||
if (fPath[strlen(fPath)-1] != PATH_SEPARATOR)
|
||||
path = path + PATH_SEPARATOR_STR + "*";
|
||||
else
|
||||
path = path + "*";
|
||||
}
|
||||
|
||||
if(glob(path.c_str(), 0, NULL, &fData->fGlobBuf) != 0 ) {
|
||||
return false;
|
||||
}
|
||||
fData->fInited=true;
|
||||
fData->fCnt = 0;
|
||||
}
|
||||
|
||||
return fData->fCnt++ < fData->fGlobBuf.gl_pathc;
|
||||
}
|
||||
|
||||
const char* hsFolderIterator::GetFileName() const
|
||||
{
|
||||
if (!fData->fInited || fData->fCnt > fData->fGlobBuf.gl_pathc)
|
||||
throw "end of folder";
|
||||
|
||||
const char* fn=fData->fGlobBuf.gl_pathv[fData->fCnt-1];
|
||||
return plFileUtils::GetFileName(fn);
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::IsDirectory( void ) const
|
||||
{
|
||||
// rob, please forgive me, this is my best attempt...
|
||||
if(fData->fCnt > fData->fGlobBuf.gl_pathc )
|
||||
return false;
|
||||
|
||||
struct stat info;
|
||||
const char* fn=fData->fGlobBuf.gl_pathv[fData->fCnt-1];
|
||||
if( stat( fn, &info ) )
|
||||
{
|
||||
printf("Error calling stat(): %s errno=%d\n", strerror(errno), errno);
|
||||
return false;
|
||||
}
|
||||
return ( info.st_mode & S_IFDIR ) ? true : false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
320
Sources/Plasma/PubUtilLib/plFile/hsFiles_Win.cpp
Normal file
320
Sources/Plasma/PubUtilLib/plFile/hsFiles_Win.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/*==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 "hsFiles.h"
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "hsExceptions.h"
|
||||
|
||||
struct hsFolderIterator_Data {
|
||||
HANDLE fSearchHandle;
|
||||
WIN32_FIND_DATA fFindData;
|
||||
Boolean fValid;
|
||||
};
|
||||
|
||||
hsFolderIterator::hsFolderIterator(const char path[], bool useCustomFilter)
|
||||
{
|
||||
fCustomFilter = useCustomFilter;
|
||||
|
||||
fData = TRACKED_NEW hsFolderIterator_Data;
|
||||
fData->fSearchHandle = nil;
|
||||
fData->fValid = true;
|
||||
|
||||
if(useCustomFilter)
|
||||
{
|
||||
this->SetFileFilterStr(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
hsFolderIterator::~hsFolderIterator()
|
||||
{
|
||||
delete fData;
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetPath(const char path[])
|
||||
{
|
||||
fCustomFilter = false;
|
||||
fPath[0] = 0;
|
||||
if (path)
|
||||
{
|
||||
::strcpy(fPath, path);
|
||||
|
||||
// Make sure the dir ends with a slash
|
||||
char lastchar = fPath[strlen(fPath)-1];
|
||||
if (lastchar != '\\' && lastchar != '/')
|
||||
strcat(fPath, "\\");
|
||||
}
|
||||
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetWinSystemDir(const char subdir[])
|
||||
{
|
||||
int ret = GetWindowsDirectory(fPath, _MAX_PATH);
|
||||
hsAssert(ret != 0, "Error getting windows directory in UseWindowsFontsPath");
|
||||
|
||||
if (subdir)
|
||||
{ ::strcat(fPath, "\\");
|
||||
::strcat(fPath, subdir);
|
||||
::strcat(fPath, "\\");
|
||||
}
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
void hsFolderIterator::SetFileFilterStr(const char filterStr[])
|
||||
{
|
||||
fPath[0] = 0;
|
||||
if (filterStr)
|
||||
{
|
||||
fCustomFilter = true;
|
||||
::strcpy(fPath, filterStr);
|
||||
}
|
||||
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void hsFolderIterator::Reset()
|
||||
{
|
||||
if (fData->fSearchHandle)
|
||||
{ FindClose(fData->fSearchHandle);
|
||||
fData->fSearchHandle = nil;
|
||||
}
|
||||
fData->fValid = true;
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::NextFile()
|
||||
{
|
||||
if (fData->fValid == false)
|
||||
return false;
|
||||
|
||||
if (fData->fSearchHandle == nil)
|
||||
{ int len = ::strlen(fPath);
|
||||
|
||||
if(fCustomFilter == false)
|
||||
{
|
||||
fPath[len] = '*';
|
||||
fPath[len+1] = 0;
|
||||
}
|
||||
|
||||
fData->fSearchHandle = FindFirstFile(fPath, &fData->fFindData);
|
||||
fPath[len] = 0;
|
||||
|
||||
if (fData->fSearchHandle == INVALID_HANDLE_VALUE)
|
||||
{ fData->fSearchHandle = nil;
|
||||
fData->fValid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ if (FindNextFile(fData->fSearchHandle, &fData->fFindData) == false)
|
||||
{ FindClose(fData->fSearchHandle);
|
||||
fData->fSearchHandle = nil;
|
||||
fData->fValid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool hsFolderIterator::IsDirectory( void ) const
|
||||
{
|
||||
if( fData->fValid && ( fData->fFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* hsFolderIterator::GetFileName() const
|
||||
{
|
||||
if (fData->fValid == false)
|
||||
hsThrow( "end of folder");
|
||||
|
||||
return fData->fFindData.cFileName;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct hsWFolderIterator_Data {
|
||||
HANDLE fSearchHandle;
|
||||
WIN32_FIND_DATAW fFindData;
|
||||
Boolean fValid;
|
||||
};
|
||||
|
||||
hsWFolderIterator::hsWFolderIterator(const wchar path[], bool useCustomFilter)
|
||||
{
|
||||
fCustomFilter = useCustomFilter;
|
||||
|
||||
fData = TRACKED_NEW hsWFolderIterator_Data;
|
||||
fData->fSearchHandle = nil;
|
||||
fData->fValid = true;
|
||||
|
||||
if(useCustomFilter)
|
||||
SetFileFilterStr(path);
|
||||
else
|
||||
SetPath(path);
|
||||
}
|
||||
|
||||
hsWFolderIterator::~hsWFolderIterator()
|
||||
{
|
||||
delete fData;
|
||||
}
|
||||
|
||||
void hsWFolderIterator::SetPath(const wchar path[])
|
||||
{
|
||||
fCustomFilter = false;
|
||||
fPath[0] = 0;
|
||||
if (path)
|
||||
{
|
||||
wcscpy(fPath, path);
|
||||
|
||||
// Make sure the dir ends with a slash
|
||||
wchar lastchar = fPath[wcslen(fPath)-1];
|
||||
if (lastchar != L'\\' && lastchar != L'/')
|
||||
wcscat(fPath, L"\\");
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void hsWFolderIterator::SetWinSystemDir(const wchar subdir[])
|
||||
{
|
||||
int ret = GetWindowsDirectoryW(fPath, _MAX_PATH);
|
||||
hsAssert(ret != 0, "Error getting windows directory in UseWindowsFontsPath");
|
||||
|
||||
if (subdir)
|
||||
{
|
||||
wcscat(fPath, L"\\");
|
||||
wcscat(fPath, subdir);
|
||||
wcscat(fPath, L"\\");
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
void hsWFolderIterator::SetFileFilterStr(const wchar filterStr[])
|
||||
{
|
||||
fPath[0] = 0;
|
||||
if (filterStr)
|
||||
{
|
||||
fCustomFilter = true;
|
||||
wcscpy(fPath, filterStr);
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void hsWFolderIterator::Reset()
|
||||
{
|
||||
if (fData->fSearchHandle)
|
||||
{
|
||||
FindClose(fData->fSearchHandle);
|
||||
fData->fSearchHandle = nil;
|
||||
}
|
||||
fData->fValid = true;
|
||||
}
|
||||
|
||||
hsBool hsWFolderIterator::NextFile()
|
||||
{
|
||||
if (fData->fValid == false)
|
||||
return false;
|
||||
|
||||
if (fData->fSearchHandle == nil)
|
||||
{
|
||||
int len = wcslen(fPath);
|
||||
|
||||
if(fCustomFilter == false)
|
||||
{
|
||||
fPath[len] = L'*';
|
||||
fPath[len+1] = L'\0';
|
||||
}
|
||||
|
||||
fData->fSearchHandle = FindFirstFileW(fPath, &fData->fFindData);
|
||||
fPath[len] = 0;
|
||||
|
||||
if (fData->fSearchHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fData->fSearchHandle = nil;
|
||||
fData->fValid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FindNextFileW(fData->fSearchHandle, &fData->fFindData) == false)
|
||||
{
|
||||
FindClose(fData->fSearchHandle);
|
||||
fData->fSearchHandle = nil;
|
||||
fData->fValid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool hsWFolderIterator::IsDirectory( void ) const
|
||||
{
|
||||
if( fData->fValid && ( fData->fFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const wchar* hsWFolderIterator::GetFileName() const
|
||||
{
|
||||
if (fData->fValid == false)
|
||||
hsThrow( "end of folder");
|
||||
|
||||
return fData->fFindData.cFileName;
|
||||
}
|
||||
|
||||
#endif // HS_BUILD_FOR_WIN32
|
88
Sources/Plasma/PubUtilLib/plFile/plBrowseFolder.cpp
Normal file
88
Sources/Plasma/PubUtilLib/plFile/plBrowseFolder.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*==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 "plBrowseFolder.h"
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
bool plBrowseFolder::GetFolder(char *path, const char *startPath, const char *title, HWND hwndOwner)
|
||||
{
|
||||
BROWSEINFO bi;
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.hwndOwner = hwndOwner;
|
||||
bi.lpszTitle = title;
|
||||
bi.lpfn = BrowseCallbackProc;
|
||||
bi.lParam = (LPARAM) startPath;
|
||||
|
||||
ITEMIDLIST *iil = SHBrowseForFolder(&bi);
|
||||
// Browse failed, or cancel was selected
|
||||
if (!iil)
|
||||
return false;
|
||||
// Browse succeded. Get the path.
|
||||
else
|
||||
SHGetPathFromIDList(iil, path);
|
||||
|
||||
// Free the memory allocated by SHBrowseForFolder
|
||||
LPMALLOC pMalloc;
|
||||
SHGetMalloc(&pMalloc);
|
||||
pMalloc->Free(iil);
|
||||
pMalloc->Release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CALLBACK plBrowseFolder::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case BFFM_INITIALIZED:
|
||||
// lpData should be the lParam passed to SHBrowseForFolder, which is the start path.
|
||||
if (lpData)
|
||||
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // HS_BUILD_FOR_WIN32
|
74
Sources/Plasma/PubUtilLib/plFile/plBrowseFolder.h
Normal file
74
Sources/Plasma/PubUtilLib/plFile/plBrowseFolder.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*==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==*/
|
||||
#ifndef plBrowseFolder_h_inc
|
||||
#define plBrowseFolder_h_inc
|
||||
|
||||
#include "hsConfig.h"
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
#include "hsWindows.h"
|
||||
|
||||
//
|
||||
// Gets a directory using the "Browse for Folder" dialog.
|
||||
//
|
||||
// path: Buffer to recieve the path. Should be MAX_PATH characters.
|
||||
// startPath: Initial path.
|
||||
// title: Not really the title of the dialog, but it's displayed above the
|
||||
// folder list. Could be used to give instructions.
|
||||
// hwndOwner: Owner window for dialog box.
|
||||
//
|
||||
// Returns true if path contains a valid path, false otherwise (error or user
|
||||
// clicked cancel.
|
||||
//
|
||||
|
||||
class plBrowseFolder
|
||||
{
|
||||
public:
|
||||
static bool GetFolder(char *path, const char *startPath = NULL, const char *title = NULL, HWND hwndOwner = NULL);
|
||||
|
||||
protected:
|
||||
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
|
||||
};
|
||||
|
||||
#endif // HS_BUILD_FOR_WIN32
|
||||
|
||||
#endif // plBrowseFolder_h_inc
|
593
Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp
Normal file
593
Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp
Normal file
@ -0,0 +1,593 @@
|
||||
/*==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 "plEncryptedStream.h"
|
||||
#include "hsUtils.h"
|
||||
#include "plFileUtils.h"
|
||||
#include "hsSTLStream.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
static const UInt32 kDefaultKey[4] = { 0x6c0a5452, 0x3827d0f, 0x3a170b92, 0x16db7fc2 };
|
||||
static const int kEncryptChunkSize = 8;
|
||||
|
||||
static const char* kOldMagicString = "BriceIsSmart";
|
||||
static const char* kMagicString = "whatdoyousee";
|
||||
static const int kMagicStringLen = 12;
|
||||
|
||||
static const int kFileStartOffset = kMagicStringLen + sizeof(UInt32);
|
||||
|
||||
static const int kMaxBufferedFileSize = 10*1024;
|
||||
|
||||
plEncryptedStream::plEncryptedStream(UInt32* key) :
|
||||
fRef(nil),
|
||||
fActualFileSize(0),
|
||||
fBufferedStream(false),
|
||||
fRAMStream(nil),
|
||||
fWriteFileName(nil),
|
||||
fOpenMode(kOpenFail)
|
||||
{
|
||||
if (key)
|
||||
memcpy(&fKey, key, sizeof(kDefaultKey));
|
||||
else
|
||||
memcpy(&fKey, &kDefaultKey, sizeof(kDefaultKey));
|
||||
}
|
||||
|
||||
plEncryptedStream::~plEncryptedStream()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Tiny Encryption Algorithm
|
||||
// http://vader.brad.ac.uk/tea/tea.shtml
|
||||
//
|
||||
// A potential weakness in this implementation is the fact that a known value
|
||||
// (length of the original file) is written at the start of the encrypted file. -Colin
|
||||
//
|
||||
// Oh, and also there's some kind of potential weakness in TEA that they fixed with XTEA,
|
||||
// but frankly, who cares. No one is going to break the encryption, they'll just get the
|
||||
// key out of the exe or memory.
|
||||
//
|
||||
void plEncryptedStream::IEncipher(UInt32* const v)
|
||||
{
|
||||
register unsigned long y=v[0], z=v[1], sum=0, delta=0x9E3779B9, n=32;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
y += (z << 4 ^ z >> 5) + z ^ sum + fKey[sum&3];
|
||||
sum += delta;
|
||||
z += (y << 4 ^ y >> 5) + y ^ sum + fKey[sum>>11 & 3];
|
||||
}
|
||||
|
||||
v[0]=y; v[1]=z;
|
||||
}
|
||||
|
||||
void plEncryptedStream::IDecipher(UInt32* const v)
|
||||
{
|
||||
register unsigned long y=v[0], z=v[1], sum=0xC6EF3720, delta=0x9E3779B9, n=32;
|
||||
|
||||
// sum = delta<<5, in general sum = delta * n
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
z -= (y << 4 ^ y >> 5) + y ^ sum + fKey[sum>>11 & 3];
|
||||
sum -= delta;
|
||||
y -= (z << 4 ^ z >> 5) + z ^ sum + fKey[sum&3];
|
||||
}
|
||||
|
||||
v[0]=y; v[1]=z;
|
||||
}
|
||||
|
||||
hsBool plEncryptedStream::Open(const char* name, const char* mode)
|
||||
{
|
||||
wchar* wName = hsStringToWString(name);
|
||||
wchar* wMode = hsStringToWString(mode);
|
||||
hsBool ret = Open(wName, wMode);
|
||||
delete [] wName;
|
||||
delete [] wMode;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsBool plEncryptedStream::Open(const wchar* name, const wchar* mode)
|
||||
{
|
||||
if (wcscmp(mode, L"rb") == 0)
|
||||
{
|
||||
fRef = _wfopen(name, mode);
|
||||
fPosition = 0;
|
||||
|
||||
if (!fRef)
|
||||
return false;
|
||||
|
||||
// Make sure our special magic string is there
|
||||
if (!ICheckMagicString(fRef))
|
||||
{
|
||||
fclose(fRef);
|
||||
return false;
|
||||
}
|
||||
|
||||
fread(&fActualFileSize, sizeof(UInt32), 1, fRef);
|
||||
|
||||
// The encrypted stream is inefficient if you do reads smaller than
|
||||
// 8 bytes. Since we do a lot of those, any file under a size threshold
|
||||
// is buffered in memory
|
||||
if (fActualFileSize <= kMaxBufferedFileSize)
|
||||
IBufferFile();
|
||||
|
||||
fOpenMode = kOpenRead;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (wcscmp(mode, L"wb") == 0)
|
||||
{
|
||||
fRAMStream = TRACKED_NEW hsVectorStream;
|
||||
fWriteFileName = TRACKED_NEW wchar[wcslen(name) + 1];
|
||||
wcscpy(fWriteFileName, name);
|
||||
fPosition = 0;
|
||||
|
||||
fOpenMode = kOpenWrite;
|
||||
fBufferedStream = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsAssert(0, "Unsupported open mode");
|
||||
fOpenMode = kOpenFail;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plEncryptedStream::Close()
|
||||
{
|
||||
int rtn = false;
|
||||
|
||||
if (fOpenMode == kOpenWrite)
|
||||
{
|
||||
fRAMStream->Rewind();
|
||||
rtn = IWriteEncypted(fRAMStream, fWriteFileName);
|
||||
}
|
||||
if (fRef)
|
||||
{
|
||||
rtn = (fclose(fRef) == 0);
|
||||
fRef = nil;
|
||||
}
|
||||
|
||||
if (fRAMStream)
|
||||
{
|
||||
delete fRAMStream;
|
||||
fRAMStream = nil;
|
||||
}
|
||||
|
||||
if (fWriteFileName)
|
||||
{
|
||||
delete [] fWriteFileName;
|
||||
fWriteFileName = nil;
|
||||
}
|
||||
|
||||
fActualFileSize = 0;
|
||||
fBufferedStream = false;
|
||||
fOpenMode = kOpenFail;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
UInt32 plEncryptedStream::IRead(UInt32 bytes, void* buffer)
|
||||
{
|
||||
if (!fRef)
|
||||
return 0;
|
||||
int numItems = (int)(::fread(buffer, 1 /*size*/, bytes /*count*/, fRef));
|
||||
fBytesRead += numItems;
|
||||
fPosition += numItems;
|
||||
if ((unsigned)numItems < bytes) {
|
||||
if (feof(fRef)) {
|
||||
// EOF ocurred
|
||||
char str[128];
|
||||
sprintf(str, "Hit EOF on UNIX Read, only read %d out of requested %d bytes\n", numItems, bytes);
|
||||
hsDebugMessage(str, 0);
|
||||
}
|
||||
else {
|
||||
hsDebugMessage("Error on UNIX Read", ferror(fRef));
|
||||
}
|
||||
}
|
||||
return numItems;
|
||||
}
|
||||
|
||||
void plEncryptedStream::IBufferFile()
|
||||
{
|
||||
fRAMStream = TRACKED_NEW hsVectorStream;
|
||||
char buf[1024];
|
||||
while (!AtEnd())
|
||||
{
|
||||
UInt32 numRead = Read(1024, buf);
|
||||
fRAMStream->Write(numRead, buf);
|
||||
}
|
||||
fRAMStream->Rewind();
|
||||
|
||||
fBufferedStream = true;
|
||||
fclose(fRef);
|
||||
fRef = nil;
|
||||
fPosition = 0;
|
||||
}
|
||||
|
||||
hsBool plEncryptedStream::AtEnd()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
return fRAMStream->AtEnd();
|
||||
else
|
||||
return (GetPosition() == fActualFileSize);
|
||||
}
|
||||
|
||||
void plEncryptedStream::Skip(UInt32 delta)
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->Skip(delta);
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef)
|
||||
{
|
||||
fBytesRead += delta;
|
||||
fPosition += delta;
|
||||
fseek(fRef, delta, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
void plEncryptedStream::Rewind()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->Rewind();
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef)
|
||||
{
|
||||
fBytesRead = 0;
|
||||
fPosition = 0;
|
||||
fseek(fRef, kFileStartOffset, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
void plEncryptedStream::FastFwd()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->FastFwd();
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef)
|
||||
{
|
||||
fseek(fRef, kFileStartOffset+fActualFileSize, SEEK_SET);
|
||||
fBytesRead = fPosition = ftell(fRef);
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 plEncryptedStream::GetEOF()
|
||||
{
|
||||
return fActualFileSize;
|
||||
}
|
||||
|
||||
UInt32 plEncryptedStream::Read(UInt32 bytes, void* buffer)
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
UInt32 numRead = fRAMStream->Read(bytes, buffer);
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
return numRead;
|
||||
}
|
||||
|
||||
UInt32 startPos = fPosition;
|
||||
|
||||
// Offset into the first buffer (0 if we are aligned on a chunk, which means no extra block read)
|
||||
UInt32 startChunkPos = startPos % kEncryptChunkSize;
|
||||
// Amount of data in the partial first chunk (0 if we're aligned)
|
||||
UInt32 startAmt = (startChunkPos != 0) ? hsMinimum(kEncryptChunkSize - startChunkPos, bytes) : 0;
|
||||
|
||||
UInt32 totalNumRead = IRead(bytes, buffer);
|
||||
|
||||
UInt32 numMidChunks = (totalNumRead - startAmt) / kEncryptChunkSize;
|
||||
UInt32 endAmt = (totalNumRead - startAmt) % kEncryptChunkSize;
|
||||
|
||||
// If the start position is in the middle of a chunk we need to rewind and
|
||||
// read that whole chunk in and decrypt it.
|
||||
if (startChunkPos != 0)
|
||||
{
|
||||
// Move to the start of this chunk
|
||||
SetPosition(startPos-startChunkPos);
|
||||
|
||||
// Read in the chunk and decrypt it
|
||||
char buf[kEncryptChunkSize];
|
||||
UInt32 numRead = IRead(kEncryptChunkSize, &buf);
|
||||
IDecipher((UInt32*)&buf);
|
||||
|
||||
// Copy the relevant portion to the output buffer
|
||||
memcpy(buffer, &buf[startChunkPos], startAmt);
|
||||
|
||||
SetPosition(startPos+totalNumRead);
|
||||
}
|
||||
|
||||
if (numMidChunks != 0)
|
||||
{
|
||||
UInt32* bufferPos = (UInt32*)(((char*)buffer)+startAmt);
|
||||
for (int i = 0; i < numMidChunks; i++)
|
||||
{
|
||||
// Decrypt chunk
|
||||
IDecipher(bufferPos);
|
||||
bufferPos += (kEncryptChunkSize / sizeof(UInt32));
|
||||
}
|
||||
}
|
||||
|
||||
if (endAmt != 0)
|
||||
{
|
||||
// Read in the final chunk and decrypt it
|
||||
char buf[kEncryptChunkSize];
|
||||
SetPosition(startPos + startAmt + numMidChunks*kEncryptChunkSize);
|
||||
UInt32 numRead = IRead(kEncryptChunkSize, &buf);
|
||||
IDecipher((UInt32*)&buf);
|
||||
|
||||
memcpy(((char*)buffer)+totalNumRead-endAmt, &buf, endAmt);
|
||||
|
||||
SetPosition(startPos+totalNumRead);
|
||||
}
|
||||
|
||||
// If we read into the padding at the end, update the total read to not include that
|
||||
if (totalNumRead > 0 && startPos + totalNumRead > fActualFileSize)
|
||||
{
|
||||
totalNumRead -= (startPos + totalNumRead) - fActualFileSize;
|
||||
SetPosition(fActualFileSize);
|
||||
}
|
||||
|
||||
return totalNumRead;
|
||||
}
|
||||
|
||||
UInt32 plEncryptedStream::Write(UInt32 bytes, const void* buffer)
|
||||
{
|
||||
if (fOpenMode != kOpenWrite)
|
||||
{
|
||||
hsAssert(0, "Trying to write to a read stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fRAMStream->Write(bytes, buffer);
|
||||
}
|
||||
|
||||
bool plEncryptedStream::IWriteEncypted(hsStream* sourceStream, const wchar* outputFile)
|
||||
{
|
||||
hsUNIXStream outputStream;
|
||||
|
||||
if (!outputStream.Open(outputFile, L"wb"))
|
||||
return false;
|
||||
|
||||
outputStream.Write(kMagicStringLen, kMagicString);
|
||||
|
||||
// Save some space to write the file size at the end
|
||||
outputStream.WriteSwap32(0);
|
||||
|
||||
// Write out all the full size encrypted blocks we can
|
||||
char buf[kEncryptChunkSize];
|
||||
UInt32 amtRead;
|
||||
while ((amtRead = sourceStream->Read(kEncryptChunkSize, &buf)) == kEncryptChunkSize)
|
||||
{
|
||||
IEncipher((UInt32*)&buf);
|
||||
outputStream.Write(kEncryptChunkSize, &buf);
|
||||
}
|
||||
|
||||
// Pad with random data and write out the final partial block, if there is one
|
||||
if (amtRead > 0)
|
||||
{
|
||||
static bool seededRand = false;
|
||||
if (!seededRand)
|
||||
{
|
||||
seededRand = true;
|
||||
srand((unsigned int)time(nil));
|
||||
}
|
||||
|
||||
for (int i = amtRead; i < kEncryptChunkSize; i++)
|
||||
buf[i] = rand();
|
||||
|
||||
IEncipher((UInt32*)&buf);
|
||||
|
||||
outputStream.Write(kEncryptChunkSize, &buf);
|
||||
}
|
||||
|
||||
// Write the original file size at the start
|
||||
UInt32 actualSize = sourceStream->GetPosition();
|
||||
outputStream.Rewind();
|
||||
outputStream.Skip(kMagicStringLen);
|
||||
outputStream.WriteSwap32(actualSize);
|
||||
|
||||
outputStream.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::FileEncrypt(const char* fileName)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = FileEncrypt(wFilename);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::FileEncrypt(const wchar* fileName)
|
||||
{
|
||||
hsUNIXStream sIn;
|
||||
if (!sIn.Open(fileName))
|
||||
return false;
|
||||
|
||||
// Don't double encrypt any files
|
||||
if (ICheckMagicString(sIn.GetFILE()))
|
||||
{
|
||||
sIn.Close();
|
||||
return true;
|
||||
}
|
||||
sIn.Rewind();
|
||||
|
||||
plEncryptedStream sOut;
|
||||
bool wroteEncrypted = sOut.IWriteEncypted(&sIn, L"crypt.dat");
|
||||
|
||||
sIn.Close();
|
||||
sOut.Close();
|
||||
|
||||
if (wroteEncrypted)
|
||||
{
|
||||
plFileUtils::RemoveFile(fileName);
|
||||
plFileUtils::FileMove(L"crypt.dat", fileName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::FileDecrypt(const char* fileName)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = FileDecrypt(wFilename);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::FileDecrypt(const wchar* fileName)
|
||||
{
|
||||
plEncryptedStream sIn;
|
||||
if (!sIn.Open(fileName))
|
||||
return false;
|
||||
|
||||
hsUNIXStream sOut;
|
||||
if (!sOut.Open(L"crypt.dat", L"wb"))
|
||||
{
|
||||
sIn.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
|
||||
while (!sIn.AtEnd())
|
||||
{
|
||||
UInt32 numRead = sIn.Read(sizeof(buf), buf);
|
||||
sOut.Write(numRead, buf);
|
||||
}
|
||||
|
||||
sIn.Close();
|
||||
sOut.Close();
|
||||
|
||||
plFileUtils::RemoveFile(fileName);
|
||||
plFileUtils::FileMove(L"crypt.dat", fileName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::ICheckMagicString(FILE* fp)
|
||||
{
|
||||
char magicString[kMagicStringLen+1];
|
||||
fread(&magicString, kMagicStringLen, 1, fp);
|
||||
magicString[kMagicStringLen] = '\0';
|
||||
return (hsStrEQ(magicString, kMagicString) || hsStrEQ(magicString, kOldMagicString));
|
||||
}
|
||||
|
||||
bool plEncryptedStream::IsEncryptedFile(const char* fileName)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = IsEncryptedFile(wFilename);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plEncryptedStream::IsEncryptedFile(const wchar* fileName)
|
||||
{
|
||||
FILE* fp = _wfopen(fileName, L"rb");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
bool isEncrypted = ICheckMagicString(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return isEncrypted;
|
||||
}
|
||||
|
||||
hsStream* plEncryptedStream::OpenEncryptedFile(const char* fileName, bool requireEncrypted, UInt32* cryptKey)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
hsStream* ret = OpenEncryptedFile(wFilename, requireEncrypted, cryptKey);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsStream* plEncryptedStream::OpenEncryptedFile(const wchar* fileName, bool requireEncrypted, UInt32* cryptKey)
|
||||
{
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
requireEncrypted = false;
|
||||
#endif
|
||||
|
||||
bool isEncrypted = IsEncryptedFile(fileName);
|
||||
|
||||
hsStream* s = nil;
|
||||
if (isEncrypted)
|
||||
s = TRACKED_NEW plEncryptedStream(cryptKey);
|
||||
// If this isn't an external release, let them use unencrypted data
|
||||
else
|
||||
if (!requireEncrypted)
|
||||
s = TRACKED_NEW hsUNIXStream;
|
||||
|
||||
if (s)
|
||||
s->Open(fileName, L"rb");
|
||||
return s;
|
||||
}
|
||||
|
||||
hsStream* plEncryptedStream::OpenEncryptedFileWrite(const char* fileName, UInt32* cryptKey)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
hsStream* ret = OpenEncryptedFileWrite(wFilename, cryptKey);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsStream* plEncryptedStream::OpenEncryptedFileWrite(const wchar* fileName, UInt32* cryptKey)
|
||||
{
|
||||
hsStream* s = nil;
|
||||
#ifdef PLASMA_EXTERNAL_RELEASE
|
||||
s = TRACKED_NEW plEncryptedStream(cryptKey);
|
||||
#else
|
||||
s = TRACKED_NEW hsUNIXStream;
|
||||
#endif
|
||||
|
||||
s->Open(fileName, L"wb");
|
||||
return s;
|
||||
}
|
116
Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.h
Normal file
116
Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.h
Normal file
@ -0,0 +1,116 @@
|
||||
/*==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==*/
|
||||
#ifndef plEncryptedStream_h_inc
|
||||
#define plEncryptedStream_h_inc
|
||||
|
||||
#include "hsStream.h"
|
||||
|
||||
//
|
||||
// Encrypt a large file by running FileEncrypt on it. Small files can be done
|
||||
// in the usual way, but they will be in memory until Close is called. Files
|
||||
// will be decrypted on the fly during read.operations
|
||||
//
|
||||
class plEncryptedStream : public hsStream
|
||||
{
|
||||
protected:
|
||||
FILE* fRef;
|
||||
UInt32 fKey[4];
|
||||
|
||||
UInt32 fActualFileSize;
|
||||
|
||||
bool fBufferedStream;
|
||||
|
||||
hsStream* fRAMStream;
|
||||
|
||||
wchar* fWriteFileName;
|
||||
|
||||
enum OpenMode { kOpenRead, kOpenWrite, kOpenFail };
|
||||
OpenMode fOpenMode;
|
||||
|
||||
void IBufferFile();
|
||||
|
||||
UInt32 IRead(UInt32 bytes, void* buffer);
|
||||
|
||||
void IEncipher(UInt32* const v);
|
||||
void IDecipher(UInt32* const v);
|
||||
|
||||
bool IWriteEncypted(hsStream* sourceStream, const wchar* outputFile);
|
||||
|
||||
static bool ICheckMagicString(FILE* fp);
|
||||
|
||||
public:
|
||||
// If you don't pass in a key (4 UInt32's), the default one will be used
|
||||
plEncryptedStream(UInt32* key=nil);
|
||||
~plEncryptedStream();
|
||||
|
||||
virtual hsBool Open(const char* name, const char* mode = "rb");
|
||||
virtual hsBool Open(const wchar* name, const wchar* mode = L"rb");
|
||||
virtual hsBool Close();
|
||||
|
||||
virtual UInt32 Read(UInt32 byteCount, void* buffer);
|
||||
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
|
||||
virtual hsBool AtEnd();
|
||||
virtual void Skip(UInt32 deltaByteCount);
|
||||
virtual void Rewind();
|
||||
virtual void FastFwd();
|
||||
virtual UInt32 GetEOF();
|
||||
|
||||
UInt32 GetActualFileSize() const { return fActualFileSize;}
|
||||
|
||||
static bool FileEncrypt(const char* fileName);
|
||||
static bool FileEncrypt(const wchar* fileName);
|
||||
static bool FileDecrypt(const char* fileName);
|
||||
static bool FileDecrypt(const wchar* fileName);
|
||||
|
||||
static bool IsEncryptedFile(const char* fileName);
|
||||
static bool IsEncryptedFile(const wchar* fileName);
|
||||
|
||||
// Attempts to create a read-binary stream for the requested file. If it's
|
||||
// encrypted, you'll get a plEncryptedStream, otherwise just a standard
|
||||
// hsUNIXStream. Remember to delete the stream when you're done with it.
|
||||
static hsStream* OpenEncryptedFile(const char* fileName, bool requireEncrypted = true, UInt32* cryptKey = nil);
|
||||
static hsStream* OpenEncryptedFile(const wchar* fileName, bool requireEncrypted = true, UInt32* cryptKey = nil);
|
||||
static hsStream* OpenEncryptedFileWrite(const char* fileName, UInt32* cryptKey = nil);
|
||||
static hsStream* OpenEncryptedFileWrite(const wchar* fileName, UInt32* cryptKey = nil);
|
||||
};
|
||||
|
||||
#endif // plEncryptedStream_h_inc
|
516
Sources/Plasma/PubUtilLib/plFile/plFileUtils.cpp
Normal file
516
Sources/Plasma/PubUtilLib/plFile/plFileUtils.cpp
Normal file
@ -0,0 +1,516 @@
|
||||
/*==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==*/
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// plFileUtils - Namespace of fun file utilities
|
||||
//
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 5.7.2002 mcn - Created
|
||||
// 4.8.2003 chip - added FileCopy and FileMove for Unix
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "hsStlUtils.h"
|
||||
#include "plFileUtils.h"
|
||||
#include "hsFiles.h"
|
||||
#include "hsStringTokenizer.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
#include "../plUnifiedTime/plUnifiedTime.h"
|
||||
|
||||
#include "plSecureStream.h" // for the default key
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#if HS_BUILD_FOR_UNIX
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
|
||||
//// CreateDir ///////////////////////////////////////////////////////////////
|
||||
// Creates the directory specified. Returns false if unsuccessful or
|
||||
// directory already exists
|
||||
|
||||
hsBool plFileUtils::CreateDir( const char *path )
|
||||
{
|
||||
// Create our directory
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return ( mkdir( path ) == 0 ) ? true : ( errno==EEXIST );
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
return ( mkdir( path, 0777 ) == 0 ) ? true : ( errno==EEXIST );
|
||||
#endif
|
||||
}
|
||||
|
||||
hsBool plFileUtils::CreateDir( const wchar *path )
|
||||
{
|
||||
// Create our directory
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return ( _wmkdir( path ) == 0 ) ? true : ( errno==EEXIST );
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
return ( mkdir( path, 0777 ) == 0 ) ? true : ( errno==EEXIST );
|
||||
#endif
|
||||
}
|
||||
|
||||
hsBool plFileUtils::RemoveDir(const char* path)
|
||||
{
|
||||
return (rmdir(path) == 0);
|
||||
}
|
||||
|
||||
hsBool plFileUtils::RemoveDirTree(const char * path)
|
||||
{
|
||||
hsFolderIterator it(path);
|
||||
while (it.NextFile())
|
||||
{
|
||||
const char * fname = it.GetFileName();
|
||||
if ( fname[0]=='.' )
|
||||
continue;
|
||||
char pathAndName[128];
|
||||
it.GetPathAndName(pathAndName);
|
||||
if ( it.IsDirectory() )
|
||||
{
|
||||
RemoveDirTree( pathAndName );
|
||||
RemoveDir( pathAndName );
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveFile( pathAndName );
|
||||
}
|
||||
}
|
||||
RemoveDir( path );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//// RemoveFile ////////////////////////////////////////////////////////////
|
||||
|
||||
bool plFileUtils::RemoveFile(const char* filename, bool delReadOnly)
|
||||
{
|
||||
if (delReadOnly)
|
||||
chmod(filename, S_IWRITE);
|
||||
return (unlink(filename) == 0);
|
||||
}
|
||||
|
||||
bool plFileUtils::RemoveFile(const wchar* filename, bool delReadOnly)
|
||||
{
|
||||
if (delReadOnly)
|
||||
_wchmod(filename, S_IWRITE);
|
||||
return (_wunlink(filename) == 0);
|
||||
}
|
||||
|
||||
bool plFileUtils::FileCopy(const char* existingFile, const char* newFile)
|
||||
{
|
||||
wchar* wExisting = hsStringToWString(existingFile);
|
||||
wchar* wNew = hsStringToWString(newFile);
|
||||
bool ret = FileCopy(wExisting, wNew);
|
||||
delete [] wExisting;
|
||||
delete [] wNew;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plFileUtils::FileCopy(const wchar* existingFile, const wchar* newFile)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return (::CopyFileW(existingFile, newFile, FALSE) != 0);
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
char data[1500];
|
||||
FILE* fp = fopen(existingFile, "rb");
|
||||
FILE* fw = fopen(newFile, "w");
|
||||
int num = 0;
|
||||
bool retVal = true;
|
||||
if (fp && fw){
|
||||
while(!feof(fp)){
|
||||
num = fread(data, sizeof( char ), 1500, fp);
|
||||
if( ferror( fp ) ) {
|
||||
retVal = false;
|
||||
break;
|
||||
}
|
||||
fwrite(data, sizeof( char ), num, fw);
|
||||
}
|
||||
fclose(fp);
|
||||
fclose(fw);
|
||||
} else {
|
||||
retVal = false;
|
||||
}
|
||||
return retVal;
|
||||
#else
|
||||
hsAssert(0, "Not implemented");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileUtils::FileMove(const char* existingFile, const char* newFile)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return (::MoveFile(existingFile, newFile) != 0);
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
FileCopy(existingFile,newFile);
|
||||
return( RemoveFile( existingFile )==0);
|
||||
#else
|
||||
hsAssert(0, "Not implemented");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileUtils::FileMove(const wchar* existingFile, const wchar* newFile)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return (::MoveFileW(existingFile, newFile) != 0);
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
FileCopy(existingFile,newFile);
|
||||
return( RemoveFile( existingFile )==0);
|
||||
#else
|
||||
hsAssert(0, "Not implemented");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileUtils::FileExists(const wchar* file)
|
||||
{
|
||||
FILE* fp = _wfopen(file, L"rb");
|
||||
bool retVal = (fp != nil);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool plFileUtils::FileExists(const char* file)
|
||||
{
|
||||
FILE* fp = fopen(file, "rb");
|
||||
bool retVal = (fp != nil);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//// EnsureFilePathExists ////////////////////////////////////////////////////
|
||||
// Given a filename with path, makes sure the file's path exists
|
||||
|
||||
hsBool plFileUtils::EnsureFilePathExists( const char *filename )
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(filename);
|
||||
hsBool ret = EnsureFilePathExists(wFilename);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsBool plFileUtils::EnsureFilePathExists( const wchar *filename )
|
||||
{
|
||||
hsWStringTokenizer izer( filename, L"\\/" );
|
||||
|
||||
hsBool lastWorked = false;
|
||||
wchar token[ kFolderIterator_MaxPath ];
|
||||
|
||||
|
||||
while( izer.Next( token, arrsize( token ) ) && izer.HasMoreTokens() )
|
||||
{
|
||||
// Want the full path from the start of the string
|
||||
lastWorked = CreateDir( izer.fString );
|
||||
izer.RestoreLastTerminator();
|
||||
}
|
||||
|
||||
return lastWorked;
|
||||
}
|
||||
|
||||
//// GetFileTimes ////////////////////////////////////////////////////////////
|
||||
// Gets the creation and modification dates of the file specified. Returns
|
||||
// false if unsuccessful
|
||||
|
||||
hsBool plFileUtils::GetFileTimes( const char *path, plUnifiedTime *createTimeOut, plUnifiedTime *modifyTimeOut )
|
||||
{
|
||||
struct stat fileInfo;
|
||||
|
||||
int result = stat( path, &fileInfo );
|
||||
if( result != 0 )
|
||||
return false;
|
||||
|
||||
if( createTimeOut != nil )
|
||||
*createTimeOut = plUnifiedTime( fileInfo.st_ctime );
|
||||
if( modifyTimeOut != nil )
|
||||
*modifyTimeOut = plUnifiedTime( fileInfo.st_mtime );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
plFileUtils::Modify plFileUtils::CompareModifyTimes(const char* file1, const char* file2)
|
||||
{
|
||||
plUnifiedTime modTime1, modTime2;
|
||||
if (GetFileTimes(file1, nil, &modTime1) &&
|
||||
GetFileTimes(file2, nil, &modTime2))
|
||||
{
|
||||
double diff = plUnifiedTime::GetTimeDifference(modTime1, modTime2);
|
||||
|
||||
if (hsABS(diff) <= 2)
|
||||
return kFilesEqual;
|
||||
else if (diff > 0)
|
||||
return kFile1Newer;
|
||||
else
|
||||
return kFile2Newer;
|
||||
}
|
||||
|
||||
return kFileError;
|
||||
}
|
||||
|
||||
bool plFileUtils::SetModifyTime( const char * filename, const plUnifiedTime & timestamp )
|
||||
{
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
HANDLE hFile = CreateFile(filename,
|
||||
GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,nil);
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
SYSTEMTIME systime;
|
||||
systime.wDay = timestamp.GetDay();
|
||||
systime.wDayOfWeek = timestamp.GetDayOfWeek();
|
||||
systime.wHour = timestamp.GetHour();
|
||||
systime.wMilliseconds = 0;
|
||||
systime.wMinute = timestamp.GetMinute();
|
||||
systime.wMonth = timestamp.GetMonth();
|
||||
systime.wSecond = timestamp.GetSecond();
|
||||
systime.wYear = timestamp.GetYear();
|
||||
FILETIME localFileTime, filetime;
|
||||
SystemTimeToFileTime(&systime,&localFileTime);
|
||||
LocalFileTimeToFileTime(&localFileTime,&filetime);
|
||||
SetFileTime(hFile,nil,nil,&filetime);
|
||||
CloseHandle(hFile);
|
||||
return true;
|
||||
|
||||
#elif HS_BUILD_FOR_UNIX
|
||||
struct stat sbuf;
|
||||
int result = stat( filename, &sbuf );
|
||||
if( result )
|
||||
return false;
|
||||
struct utimbuf utb;
|
||||
utb.actime = sbuf.st_atime;
|
||||
utb.modtime = timestamp.GetSecs();
|
||||
result = utime( filename, &utb );
|
||||
if( result )
|
||||
return false;
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//// StripPath ///////////////////////////////////////////////////////////////
|
||||
|
||||
const char* plFileUtils::GetFileName(const char* path)
|
||||
{
|
||||
const char* c = strrchr(path, '/');
|
||||
if (c == nil)
|
||||
c = strrchr(path, '\\');
|
||||
|
||||
if (c == nil)
|
||||
c = path;
|
||||
else
|
||||
c++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
const wchar* plFileUtils::GetFileName(const wchar* path)
|
||||
{
|
||||
const wchar* c = wcsrchr(path, L'/');
|
||||
if (c == nil)
|
||||
c = wcsrchr(path, L'\\');
|
||||
|
||||
if (c == nil)
|
||||
c = path;
|
||||
else
|
||||
c++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void plFileUtils::StripFile(char* pathAndName)
|
||||
{
|
||||
char* fileName = (char*)GetFileName(pathAndName);
|
||||
if (fileName != pathAndName)
|
||||
*fileName = '\0';
|
||||
}
|
||||
|
||||
void plFileUtils::StripFile(wchar* pathAndName)
|
||||
{
|
||||
wchar* fileName = (wchar*)GetFileName(pathAndName);
|
||||
if (fileName != pathAndName)
|
||||
*fileName = L'\0';
|
||||
}
|
||||
|
||||
void plFileUtils::StripExt(char* fileName)
|
||||
{
|
||||
char* ext = (char*)GetFileExt(fileName);
|
||||
if (ext)
|
||||
*(ext-1) = '\0';
|
||||
}
|
||||
|
||||
const char* plFileUtils::GetFileExt(const char* pathAndName)
|
||||
{
|
||||
const char* fileName = GetFileName(pathAndName);
|
||||
if (fileName)
|
||||
{
|
||||
const char* ext = strrchr(fileName, '.');
|
||||
if (ext)
|
||||
return ext+1;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
const wchar* plFileUtils::GetFileExt(const wchar* pathAndName)
|
||||
{
|
||||
const wchar* fileName = GetFileName(pathAndName);
|
||||
if (fileName)
|
||||
{
|
||||
const wchar* ext = wcsrchr(fileName, L'.');
|
||||
if (ext)
|
||||
return ext+1;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plFileUtils::AddSlash(char* path)
|
||||
{
|
||||
char lastChar = path[strlen(path)-1];
|
||||
if (lastChar != '\\' && lastChar != '/')
|
||||
strcat(path, "\\");
|
||||
}
|
||||
|
||||
void plFileUtils::ConcatFileName(char* path, const char* fileName)
|
||||
{
|
||||
AddSlash(path);
|
||||
strcat(path, fileName);
|
||||
}
|
||||
|
||||
//// GetFileSize /////////////////////////////////////////////////////////////
|
||||
|
||||
UInt32 plFileUtils::GetFileSize( const char *path )
|
||||
{
|
||||
wchar* wPath = hsStringToWString(path);
|
||||
UInt32 ret = GetFileSize(wPath);
|
||||
delete [] wPath;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UInt32 plFileUtils::GetFileSize( const wchar *path )
|
||||
{
|
||||
UInt32 len = 0;
|
||||
|
||||
hsUNIXStream str;
|
||||
if (str.Open(path, L"rb"))
|
||||
{
|
||||
len = str.GetEOF();
|
||||
str.Close();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
//// GetSecureEncryptionKey //////////////////////////////////////////////////
|
||||
|
||||
bool plFileUtils::GetSecureEncryptionKey(const char* filename, UInt32* key, unsigned length)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(filename);
|
||||
bool ret = GetSecureEncryptionKey(wFilename, key, length);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plFileUtils::GetSecureEncryptionKey(const wchar* filename, UInt32* key, unsigned length)
|
||||
{
|
||||
// looks for an encryption key file in the same directory, and reads it
|
||||
std::wstring sFilename = filename;
|
||||
|
||||
// grab parent directory
|
||||
unsigned loc = sFilename.rfind(L"\\");
|
||||
if (loc == std::wstring::npos)
|
||||
loc = sFilename.rfind(L"/");
|
||||
|
||||
std::wstring sDir;
|
||||
if (loc != std::wstring::npos)
|
||||
sDir = sFilename.substr(0, loc);
|
||||
else // no directory
|
||||
sDir = L"./";
|
||||
if ((sDir[sDir.length()-1] != L'/') && (sDir[sDir.length()-1] != L'\\'))
|
||||
sDir += L'/'; // add the slash, if it doesn't has one
|
||||
|
||||
// now add the key filename
|
||||
std::wstring keyFile = sDir + kWKeyFilename;
|
||||
|
||||
if (FileExists(keyFile.c_str()))
|
||||
{
|
||||
// file exists, read from it
|
||||
hsUNIXStream file;
|
||||
file.Open(keyFile.c_str(), L"rb");
|
||||
|
||||
unsigned bytesToRead = length * sizeof(UInt32);
|
||||
byte* buffer = (byte*)ALLOC(bytesToRead);
|
||||
unsigned bytesRead = file.Read(bytesToRead, buffer);
|
||||
|
||||
file.Close();
|
||||
|
||||
unsigned memSize = min(bytesToRead, bytesRead);
|
||||
memcpy(key, buffer, memSize);
|
||||
FREE(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist, use default key
|
||||
unsigned memSize = min(length, arrsize(plSecureStream::kDefaultKey));
|
||||
memSize *= sizeof(UInt32);
|
||||
memcpy(key, plSecureStream::kDefaultKey, memSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
122
Sources/Plasma/PubUtilLib/plFile/plFileUtils.h
Normal file
122
Sources/Plasma/PubUtilLib/plFile/plFileUtils.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*==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==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// plFileUtils - Namespace of fun file utilities
|
||||
//
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 5.7.2002 mcn - Created
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plFileUtils_h
|
||||
#define _plFileUtils_h
|
||||
|
||||
class plUnifiedTime;
|
||||
|
||||
namespace plFileUtils
|
||||
{
|
||||
static const char kKeyFilename[] = "encryption.key";
|
||||
static const wchar kWKeyFilename[] = L"encryption.key";
|
||||
|
||||
// Creates the directory specified. Returns false if unsuccessful or directory already exists
|
||||
hsBool CreateDir( const char *path );
|
||||
hsBool CreateDir( const wchar *path );
|
||||
hsBool RemoveDir(const char* path);
|
||||
hsBool RemoveDirTree(const char * path);
|
||||
|
||||
// delete file from disk
|
||||
bool RemoveFile(const char* filename, bool delReadOnly=false);
|
||||
bool RemoveFile(const wchar* filename, bool delReadOnly=false);
|
||||
|
||||
bool FileCopy(const char* existingFile, const char* newFile);
|
||||
bool FileCopy(const wchar* existingFile, const wchar* newFile);
|
||||
bool FileMove(const char* existingFile, const char* newFile);
|
||||
bool FileMove(const wchar* existingFile, const wchar* newFile);
|
||||
|
||||
bool FileExists(const char* file);
|
||||
bool FileExists(const wchar* file);
|
||||
|
||||
// Given a filename with path, makes sure the file's path exists
|
||||
hsBool EnsureFilePathExists( const char *filename );
|
||||
hsBool EnsureFilePathExists( const wchar *filename );
|
||||
|
||||
// Gets the creation and modification dates of the file specified. Returns false if unsuccessful
|
||||
hsBool GetFileTimes( const char *path, plUnifiedTime *createTimeOut, plUnifiedTime *modifyTimeOut );
|
||||
// Compares file times, taking into account NTFS/FAT32 time issues
|
||||
enum Modify { kFileError, kFilesEqual, kFile1Newer, kFile2Newer };
|
||||
Modify CompareModifyTimes(const char* file1, const char* file2);
|
||||
// Set file modify time
|
||||
bool SetModifyTime( const char * filename, const plUnifiedTime & time );
|
||||
|
||||
// Return a pointer into the given string at the start of the actual filename (i.e. past any path info)
|
||||
const char* GetFileName(const char* pathAndName);
|
||||
const wchar* GetFileName(const wchar* pathAndName);
|
||||
// Get the file extension (without the .), or nil if it doesn't have one
|
||||
const char* GetFileExt(const char* pathAndName);
|
||||
const wchar* GetFileExt(const wchar* pathAndName);
|
||||
|
||||
// Strips the filename off the given full path
|
||||
void StripFile(char* pathAndName);
|
||||
void StripFile(wchar* pathAndName);
|
||||
void StripExt(char* fileName);
|
||||
|
||||
// Get the size of the given file in bytes
|
||||
UInt32 GetFileSize( const char *path );
|
||||
UInt32 GetFileSize( const wchar *path );
|
||||
|
||||
// Adds a slash to the end of a filename (or does nothing if it's already there)
|
||||
void AddSlash(char* path);
|
||||
|
||||
// Concatenates fileName onto path, making sure to add a slash if necessary
|
||||
void ConcatFileName(char* path, const char* fileName);
|
||||
|
||||
// searches the parent directory of filename for the encryption key file, and reads it
|
||||
// into the key passed in. Returns false if the key file didn't exist (and sets key to
|
||||
// the default key)
|
||||
bool GetSecureEncryptionKey(const char* filename, UInt32* key, unsigned length);
|
||||
bool GetSecureEncryptionKey(const wchar* filename, UInt32* key, unsigned length);
|
||||
};
|
||||
|
||||
|
||||
#endif // _plFileUtils_h
|
218
Sources/Plasma/PubUtilLib/plFile/plInitFileReader.cpp
Normal file
218
Sources/Plasma/PubUtilLib/plFile/plInitFileReader.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/*==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==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInitFileReader - Helper class that parses a standard-format .ini file //
|
||||
// and allows you to specify derived classes to handle //
|
||||
// interpreting specific portions. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plInitFileReader.h"
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "hsUtils.h"
|
||||
#include "hsStringTokenizer.h"
|
||||
#include "plEncryptedStream.h"
|
||||
|
||||
|
||||
plInitSectionTokenReader::plInitSectionTokenReader( const char *separators ) : fSeparators( separators )
|
||||
{
|
||||
}
|
||||
|
||||
hsBool plInitSectionTokenReader::ParseLine( const char *line, UInt32 userData )
|
||||
{
|
||||
hsStringTokenizer izer( line, fSeparators );
|
||||
|
||||
char *token = izer.next();
|
||||
return IParseToken( token, &izer, userData );
|
||||
}
|
||||
|
||||
void plInitFileReader::IInitReaders( plInitSectionReader **readerArray )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
for( i = 0; readerArray[ i ] != nil; i++ )
|
||||
fSections.Append( readerArray[ i ] );
|
||||
|
||||
hsAssert( fSections.GetCount() > 0, "No sections for initFileReader" );
|
||||
|
||||
fCurrSection = fSections[ 0 ];
|
||||
}
|
||||
|
||||
plInitFileReader::plInitFileReader( plInitSectionReader **readerArray, UInt16 lineSize )
|
||||
{
|
||||
fRequireEncrypted = true;
|
||||
fCurrLine = nil;
|
||||
fLineSize = lineSize;
|
||||
fStream = fOurStream = nil;
|
||||
IInitReaders( readerArray );
|
||||
fUnhandledSection = nil;
|
||||
}
|
||||
|
||||
plInitFileReader::plInitFileReader( const char *fileName, plInitSectionReader **readerArray, UInt16 lineSize )
|
||||
{
|
||||
fRequireEncrypted = true;
|
||||
fCurrLine = nil;
|
||||
fLineSize = lineSize;
|
||||
fStream = fOurStream = nil;
|
||||
IInitReaders( readerArray );
|
||||
if( !Open( fileName ) )
|
||||
hsAssert( false, "Constructor open for plInitFileReader failed!" );
|
||||
fUnhandledSection = nil;
|
||||
}
|
||||
|
||||
plInitFileReader::plInitFileReader( hsStream *stream, plInitSectionReader **readerArray, UInt16 lineSize )
|
||||
{
|
||||
fRequireEncrypted = true;
|
||||
fCurrLine = nil;
|
||||
fLineSize = lineSize;
|
||||
fStream = fOurStream = nil;
|
||||
IInitReaders( readerArray );
|
||||
if( !Open( stream ) )
|
||||
hsAssert( false, "Constructor open for plInitFileReader failed!" );
|
||||
fUnhandledSection = nil;
|
||||
}
|
||||
|
||||
plInitFileReader::~plInitFileReader()
|
||||
{
|
||||
Close();
|
||||
delete [] fCurrLine;
|
||||
}
|
||||
|
||||
hsBool plInitFileReader::Open( const char *fileName )
|
||||
{
|
||||
if( fStream != nil )
|
||||
{
|
||||
hsAssert( false, "Unable to open initFileReader; already open" );
|
||||
return false;
|
||||
}
|
||||
|
||||
fOurStream = plEncryptedStream::OpenEncryptedFile( fileName, fRequireEncrypted );
|
||||
|
||||
if( fOurStream == nil )
|
||||
return false;
|
||||
|
||||
fStream = fOurStream;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plInitFileReader::Open( hsStream *stream )
|
||||
{
|
||||
if( fStream != nil )
|
||||
{
|
||||
hsAssert( false, "Unable to open initFileReader; already open" );
|
||||
return false;
|
||||
}
|
||||
|
||||
fStream = stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plInitFileReader::Parse( UInt32 userData )
|
||||
{
|
||||
hsAssert( fStream != nil, "Nil stream in initFileReader::Parse(); file not yet open?" );
|
||||
|
||||
if( fCurrLine == nil )
|
||||
fCurrLine = TRACKED_NEW char[ fLineSize + 1 ];
|
||||
|
||||
// Start parsing lines
|
||||
while( fStream->ReadLn( fCurrLine, fLineSize ) )
|
||||
{
|
||||
// puts( fCurrLine );
|
||||
|
||||
// Is line a section header?
|
||||
if( fCurrLine[ 0 ] == '[' )
|
||||
{
|
||||
// Yes--match against our sections and switch to the given one
|
||||
char *end = strchr( fCurrLine, ']' );
|
||||
if( end != nil )
|
||||
*end = 0;
|
||||
|
||||
UInt32 i;
|
||||
|
||||
bool foundSection = false;
|
||||
for( i = 0; i < fSections.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fSections[ i ]->GetSectionName(), &fCurrLine[ 1 ] ) == 0 )
|
||||
{
|
||||
fCurrSection = fSections[ i ];
|
||||
foundSection = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSection && fUnhandledSection)
|
||||
{
|
||||
fCurrSection = fUnhandledSection;
|
||||
fCurrSection->SetSectionName(&fCurrLine[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nope, just a line, pass to our current section tokenizer
|
||||
if( !fCurrSection->ParseLine( fCurrLine, userData ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void plInitFileReader::Close( void )
|
||||
{
|
||||
if( fStream == nil )
|
||||
return;
|
||||
|
||||
if( fStream == fOurStream )
|
||||
{
|
||||
fStream->Close();
|
||||
delete fOurStream;
|
||||
fOurStream = nil;
|
||||
}
|
||||
|
||||
fStream = nil;
|
||||
}
|
||||
|
153
Sources/Plasma/PubUtilLib/plFile/plInitFileReader.h
Normal file
153
Sources/Plasma/PubUtilLib/plFile/plInitFileReader.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*==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==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInitFileReader - Helper class that parses a standard-format .ini file //
|
||||
// and allows you to specify derived classes to handle //
|
||||
// interpreting specific portions. //
|
||||
// //
|
||||
//// Usage ///////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// First create a set of derived classes from plInitSectionReader //
|
||||
// (or plInitSectionTokenReader, to be easier) that will parse the lines //
|
||||
// for each section of your .ini file. Then create a C-style array of //
|
||||
// pointers to instances of each reader, the first being the default //
|
||||
// reader, and ending with a nil pointer (see below). Finally, create //
|
||||
// a plInitFileReader with the array you created and it'll parse the //
|
||||
// given file (or stream) and call your readers as needed. You can also //
|
||||
// optionally pass in a UInt32 for userData that will be passed on to each //
|
||||
// reader in turn. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plInitFileReader_h
|
||||
#define _plInitFileReader_h
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
//// Base Section Class //////////////////////////////////////////////////////
|
||||
// Define a derived version of this for each section of your init file.
|
||||
|
||||
class plInitSectionReader
|
||||
{
|
||||
public:
|
||||
|
||||
// Override this to define what [string] your section starts with
|
||||
virtual const char *GetSectionName( void ) const = 0;
|
||||
|
||||
// Override this to parse each line in your section. Return false to abort parsing
|
||||
virtual hsBool ParseLine( const char *line, UInt32 userData ) = 0;
|
||||
|
||||
// Override this if you're defining an unhandled section reader
|
||||
virtual void SetSectionName(const char* section) {}
|
||||
};
|
||||
|
||||
//// Semi-Derived Class //////////////////////////////////////////////////////
|
||||
// Half-way derived class for parsing lines by tokens rather than pure
|
||||
// strings.
|
||||
|
||||
class hsStringTokenizer;
|
||||
|
||||
class plInitSectionTokenReader : public plInitSectionReader
|
||||
{
|
||||
protected:
|
||||
|
||||
const char *fSeparators;
|
||||
|
||||
// Override this to parse each token in your section. Return false to abort parsing
|
||||
virtual hsBool IParseToken( const char *token, hsStringTokenizer *tokenizer, UInt32 userData ) = 0;
|
||||
|
||||
public:
|
||||
|
||||
plInitSectionTokenReader( const char *separators = ",=\t" );
|
||||
|
||||
// Overridden for you. Override IParseToken()
|
||||
virtual hsBool ParseLine( const char *line, UInt32 userData );
|
||||
};
|
||||
|
||||
//// Main Reader Class ///////////////////////////////////////////////////////
|
||||
// Create one of these and add an array of derived versions of the above
|
||||
// reader to parse your init file.
|
||||
|
||||
class plInitFileReader
|
||||
{
|
||||
protected:
|
||||
|
||||
hsStream *fStream;
|
||||
hsStream *fOurStream;
|
||||
char *fCurrLine;
|
||||
UInt32 fLineSize;
|
||||
bool fRequireEncrypted;
|
||||
|
||||
plInitSectionReader *fCurrSection;
|
||||
hsTArray<plInitSectionReader *> fSections;
|
||||
plInitSectionReader* fUnhandledSection;
|
||||
|
||||
void IInitReaders( plInitSectionReader **readerArray );
|
||||
|
||||
public:
|
||||
|
||||
// The array passed in should be an array of pointers to plInitSectionReader,
|
||||
// with the last pointer being nil (denoting the end of the array). The first
|
||||
// element of the array will be the "default" section--i.e. if there is no section
|
||||
// header at the top of the file, that reader will be used.
|
||||
|
||||
plInitFileReader( plInitSectionReader **readerArray, UInt16 lineSize = 256 );
|
||||
plInitFileReader( const char *fileName, plInitSectionReader **readerArray, UInt16 lineSize = 256 );
|
||||
plInitFileReader( hsStream *stream, plInitSectionReader **readerArray, UInt16 lineSize = 256 );
|
||||
virtual ~plInitFileReader();
|
||||
|
||||
void SetRequireEncrypted(bool require) { fRequireEncrypted = require; }
|
||||
bool GetRequireEncrypted() const { return fRequireEncrypted; }
|
||||
void SetUnhandledSectionReader(plInitSectionReader* reader) { fUnhandledSection = reader; }
|
||||
|
||||
hsBool Open( const char *fileName );
|
||||
hsBool Open( hsStream *stream );
|
||||
hsBool Parse( UInt32 userData = 0 );
|
||||
void Close( void );
|
||||
|
||||
hsBool IsOpen( void ) const { return fStream != nil; }
|
||||
};
|
||||
|
||||
#endif //_plInitFileReader_h
|
640
Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp
Normal file
640
Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp
Normal file
@ -0,0 +1,640 @@
|
||||
/*==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 "plSecureStream.h"
|
||||
#include "hsUtils.h"
|
||||
#include "plFileUtils.h"
|
||||
#include "hsSTLStream.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
// our default encryption key
|
||||
const UInt32 plSecureStream::kDefaultKey[4] = { 0x6c0a5452, 0x3827d0f, 0x3a170b92, 0x16db7fc2 };
|
||||
|
||||
static const int kEncryptChunkSize = 8;
|
||||
|
||||
static const char* kMagicString = "notthedroids";
|
||||
static const int kMagicStringLen = 12;
|
||||
|
||||
static const int kFileStartOffset = kMagicStringLen + sizeof(UInt32);
|
||||
|
||||
static const int kMaxBufferedFileSize = 10*1024;
|
||||
|
||||
plSecureStream::plSecureStream(hsBool deleteOnExit, UInt32* key) :
|
||||
fRef(INVALID_HANDLE_VALUE),
|
||||
fActualFileSize(0),
|
||||
fBufferedStream(false),
|
||||
fRAMStream(nil),
|
||||
fWriteFileName(nil),
|
||||
fOpenMode(kOpenFail),
|
||||
fDeleteOnExit(deleteOnExit)
|
||||
{
|
||||
if (key)
|
||||
memcpy(&fKey, key, sizeof(kDefaultKey));
|
||||
else
|
||||
memcpy(&fKey, &kDefaultKey, sizeof(kDefaultKey));
|
||||
}
|
||||
|
||||
plSecureStream::~plSecureStream()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// XXTEA
|
||||
// http://www-users.cs.york.ac.uk/~matthew/TEA/
|
||||
//
|
||||
// A potential weakness in this implementation is the fact that a known value
|
||||
// (length of the original file) is written at the start of the encrypted file. -Colin
|
||||
//
|
||||
|
||||
#define MX (z>>5 ^ y<<2) + (y>>3 ^ z<<4) ^ (sum^y) + (fKey[p&3^e]^z)
|
||||
|
||||
void plSecureStream::IEncipher(UInt32* const v, UInt32 n)
|
||||
{
|
||||
register unsigned long y=v[0], z=v[n-1], e, delta=0x9E3779B9;
|
||||
register unsigned long q = 6 + 52/n, p, sum = 0;
|
||||
|
||||
while (q-- > 0)
|
||||
{
|
||||
sum += delta;
|
||||
e = (sum >> 2) & 3;
|
||||
for (p = 0; p < n - 1; p++)
|
||||
{
|
||||
y = v[p + 1];
|
||||
v[p] += MX;
|
||||
z = v[p];
|
||||
}
|
||||
y = v[0];
|
||||
v[n - 1] += MX;
|
||||
z = v[n - 1];
|
||||
}
|
||||
}
|
||||
|
||||
void plSecureStream::IDecipher(UInt32* const v, UInt32 n)
|
||||
{
|
||||
register unsigned long y=v[0], z=v[n-1], e, delta=0x9E3779B9;
|
||||
register unsigned long q = 6 + 52/n, p, sum = q * delta;
|
||||
|
||||
while (sum > 0)
|
||||
{
|
||||
e = (sum >> 2) & 3;
|
||||
for (p = n - 1; p > 0; p--)
|
||||
{
|
||||
z = v[p - 1];
|
||||
v[p] -= MX;
|
||||
y = v[p];
|
||||
}
|
||||
z = v[n - 1];
|
||||
v[0] -= MX;
|
||||
y = v[0];
|
||||
sum -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plSecureStream::Open(const char* name, const char* mode)
|
||||
{
|
||||
wchar* wName = hsStringToWString(name);
|
||||
wchar* wMode = hsStringToWString(mode);
|
||||
hsBool ret = Open(wName, wMode);
|
||||
delete [] wName;
|
||||
delete [] wMode;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsBool plSecureStream::Open(const wchar* name, const wchar* mode)
|
||||
{
|
||||
if (wcscmp(mode, L"rb") == 0)
|
||||
{
|
||||
if (fDeleteOnExit)
|
||||
{
|
||||
fRef = CreateFileW(name,
|
||||
GENERIC_READ, // open for reading
|
||||
0, // no one can open the file until we're done
|
||||
NULL, // default security
|
||||
OPEN_EXISTING, // only open existing files (no creation)
|
||||
FILE_FLAG_DELETE_ON_CLOSE, // delete the file from disk when we close the handle
|
||||
NULL); // no template
|
||||
}
|
||||
else
|
||||
{
|
||||
fRef = CreateFileW(name,
|
||||
GENERIC_READ, // open for reading
|
||||
0, // no one can open the file until we're done
|
||||
NULL, // default security
|
||||
OPEN_EXISTING, // only open existing files (no creation)
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file attributes
|
||||
NULL); // no template
|
||||
}
|
||||
|
||||
fPosition = 0;
|
||||
|
||||
if (fRef == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// Make sure our special magic string is there
|
||||
if (!ICheckMagicString(fRef))
|
||||
{
|
||||
CloseHandle(fRef);
|
||||
fRef = INVALID_HANDLE_VALUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD numBytesRead;
|
||||
ReadFile(fRef, &fActualFileSize, sizeof(UInt32), &numBytesRead, NULL);
|
||||
|
||||
// The encrypted stream is inefficient if you do reads smaller than
|
||||
// 8 bytes. Since we do a lot of those, any file under a size threshold
|
||||
// is buffered in memory
|
||||
if (fActualFileSize <= kMaxBufferedFileSize)
|
||||
IBufferFile();
|
||||
|
||||
fOpenMode = kOpenRead;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (wcscmp(mode, L"wb") == 0)
|
||||
{
|
||||
fRAMStream = TRACKED_NEW hsVectorStream;
|
||||
fWriteFileName = TRACKED_NEW wchar[wcslen(name) + 1];
|
||||
wcscpy(fWriteFileName, name);
|
||||
fPosition = 0;
|
||||
|
||||
fOpenMode = kOpenWrite;
|
||||
fBufferedStream = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsAssert(0, "Unsupported open mode");
|
||||
fOpenMode = kOpenFail;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plSecureStream::Close()
|
||||
{
|
||||
int rtn = false;
|
||||
|
||||
if (fOpenMode == kOpenWrite)
|
||||
{
|
||||
fRAMStream->Rewind();
|
||||
rtn = IWriteEncrypted(fRAMStream, fWriteFileName);
|
||||
}
|
||||
if (fRef != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
rtn = CloseHandle(fRef);
|
||||
fRef = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (fRAMStream)
|
||||
{
|
||||
delete fRAMStream;
|
||||
fRAMStream = nil;
|
||||
}
|
||||
|
||||
if (fWriteFileName)
|
||||
{
|
||||
delete [] fWriteFileName;
|
||||
fWriteFileName = nil;
|
||||
}
|
||||
|
||||
fActualFileSize = 0;
|
||||
fBufferedStream = false;
|
||||
fOpenMode = kOpenFail;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
UInt32 plSecureStream::IRead(UInt32 bytes, void* buffer)
|
||||
{
|
||||
if (fRef == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
DWORD numItems;
|
||||
bool success = (ReadFile(fRef, buffer, bytes, &numItems, NULL) != 0);
|
||||
fBytesRead += numItems;
|
||||
fPosition += numItems;
|
||||
if ((unsigned)numItems < bytes)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
// EOF ocurred
|
||||
char str[128];
|
||||
sprintf(str, "Hit EOF on Windows read, only read %d out of requested %d bytes\n", numItems, bytes);
|
||||
hsDebugMessage(str, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsDebugMessage("Error on Windows read", GetLastError());
|
||||
}
|
||||
}
|
||||
return numItems;
|
||||
}
|
||||
|
||||
void plSecureStream::IBufferFile()
|
||||
{
|
||||
fRAMStream = TRACKED_NEW hsVectorStream;
|
||||
char buf[1024];
|
||||
while (!AtEnd())
|
||||
{
|
||||
UInt32 numRead = Read(1024, buf);
|
||||
fRAMStream->Write(numRead, buf);
|
||||
}
|
||||
fRAMStream->Rewind();
|
||||
|
||||
fBufferedStream = true;
|
||||
CloseHandle(fRef);
|
||||
fRef = INVALID_HANDLE_VALUE;
|
||||
fPosition = 0;
|
||||
}
|
||||
|
||||
hsBool plSecureStream::AtEnd()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
return fRAMStream->AtEnd();
|
||||
else
|
||||
return (GetPosition() == fActualFileSize);
|
||||
}
|
||||
|
||||
void plSecureStream::Skip(UInt32 delta)
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->Skip(delta);
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fBytesRead += delta;
|
||||
fPosition += delta;
|
||||
SetFilePointer(fRef, delta, 0, FILE_CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
void plSecureStream::Rewind()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->Rewind();
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fBytesRead = 0;
|
||||
fPosition = 0;
|
||||
SetFilePointer(fRef, kFileStartOffset, 0, FILE_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
void plSecureStream::FastFwd()
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
fRAMStream->FastFwd();
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
}
|
||||
else if (fRef != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fBytesRead = fPosition = SetFilePointer(fRef, kFileStartOffset + fActualFileSize, 0, FILE_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 plSecureStream::GetEOF()
|
||||
{
|
||||
return fActualFileSize;
|
||||
}
|
||||
|
||||
UInt32 plSecureStream::Read(UInt32 bytes, void* buffer)
|
||||
{
|
||||
if (fBufferedStream)
|
||||
{
|
||||
UInt32 numRead = fRAMStream->Read(bytes, buffer);
|
||||
fPosition = fRAMStream->GetPosition();
|
||||
return numRead;
|
||||
}
|
||||
|
||||
UInt32 startPos = fPosition;
|
||||
|
||||
// Offset into the first buffer (0 if we are aligned on a chunk, which means no extra block read)
|
||||
UInt32 startChunkPos = startPos % kEncryptChunkSize;
|
||||
// Amount of data in the partial first chunk (0 if we're aligned)
|
||||
UInt32 startAmt = (startChunkPos != 0) ? hsMinimum(kEncryptChunkSize - startChunkPos, bytes) : 0;
|
||||
|
||||
UInt32 totalNumRead = IRead(bytes, buffer);
|
||||
|
||||
UInt32 numMidChunks = (totalNumRead - startAmt) / kEncryptChunkSize;
|
||||
UInt32 endAmt = (totalNumRead - startAmt) % kEncryptChunkSize;
|
||||
|
||||
// If the start position is in the middle of a chunk we need to rewind and
|
||||
// read that whole chunk in and decrypt it.
|
||||
if (startChunkPos != 0)
|
||||
{
|
||||
// Move to the start of this chunk
|
||||
SetPosition(startPos-startChunkPos);
|
||||
|
||||
// Read in the chunk and decrypt it
|
||||
char buf[kEncryptChunkSize];
|
||||
UInt32 numRead = IRead(kEncryptChunkSize, &buf);
|
||||
IDecipher((UInt32*)&buf, kEncryptChunkSize / sizeof(UInt32));
|
||||
|
||||
// Copy the relevant portion to the output buffer
|
||||
memcpy(buffer, &buf[startChunkPos], startAmt);
|
||||
|
||||
SetPosition(startPos+totalNumRead);
|
||||
}
|
||||
|
||||
if (numMidChunks != 0)
|
||||
{
|
||||
UInt32* bufferPos = (UInt32*)(((char*)buffer)+startAmt);
|
||||
for (int i = 0; i < numMidChunks; i++)
|
||||
{
|
||||
// Decrypt chunk
|
||||
IDecipher(bufferPos, kEncryptChunkSize / sizeof(UInt32));
|
||||
bufferPos += (kEncryptChunkSize / sizeof(UInt32));
|
||||
}
|
||||
}
|
||||
|
||||
if (endAmt != 0)
|
||||
{
|
||||
// Read in the final chunk and decrypt it
|
||||
char buf[kEncryptChunkSize];
|
||||
SetPosition(startPos + startAmt + numMidChunks*kEncryptChunkSize);
|
||||
UInt32 numRead = IRead(kEncryptChunkSize, &buf);
|
||||
IDecipher((UInt32*)&buf, kEncryptChunkSize / sizeof(UInt32));
|
||||
|
||||
memcpy(((char*)buffer)+totalNumRead-endAmt, &buf, endAmt);
|
||||
|
||||
SetPosition(startPos+totalNumRead);
|
||||
}
|
||||
|
||||
// If we read into the padding at the end, update the total read to not include that
|
||||
if (totalNumRead > 0 && startPos + totalNumRead > fActualFileSize)
|
||||
{
|
||||
totalNumRead -= (startPos + totalNumRead) - fActualFileSize;
|
||||
SetPosition(fActualFileSize);
|
||||
}
|
||||
|
||||
return totalNumRead;
|
||||
}
|
||||
|
||||
UInt32 plSecureStream::Write(UInt32 bytes, const void* buffer)
|
||||
{
|
||||
if (fOpenMode != kOpenWrite)
|
||||
{
|
||||
hsAssert(0, "Trying to write to a read stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fRAMStream->Write(bytes, buffer);
|
||||
}
|
||||
|
||||
bool plSecureStream::IWriteEncrypted(hsStream* sourceStream, const wchar* outputFile)
|
||||
{
|
||||
hsUNIXStream outputStream;
|
||||
|
||||
if (!outputStream.Open(outputFile, L"wb"))
|
||||
return false;
|
||||
|
||||
outputStream.Write(kMagicStringLen, kMagicString);
|
||||
|
||||
// Save some space to write the file size at the end
|
||||
outputStream.WriteSwap32(0);
|
||||
|
||||
// Write out all the full size encrypted blocks we can
|
||||
char buf[kEncryptChunkSize];
|
||||
UInt32 amtRead;
|
||||
while ((amtRead = sourceStream->Read(kEncryptChunkSize, &buf)) == kEncryptChunkSize)
|
||||
{
|
||||
IEncipher((UInt32*)&buf, kEncryptChunkSize / sizeof(UInt32));
|
||||
outputStream.Write(kEncryptChunkSize, &buf);
|
||||
}
|
||||
|
||||
// Pad with random data and write out the final partial block, if there is one
|
||||
if (amtRead > 0)
|
||||
{
|
||||
static bool seededRand = false;
|
||||
if (!seededRand)
|
||||
{
|
||||
seededRand = true;
|
||||
srand((unsigned int)time(nil));
|
||||
}
|
||||
|
||||
for (int i = amtRead; i < kEncryptChunkSize; i++)
|
||||
buf[i] = rand();
|
||||
|
||||
IEncipher((UInt32*)&buf, kEncryptChunkSize / sizeof(UInt32));
|
||||
|
||||
outputStream.Write(kEncryptChunkSize, &buf);
|
||||
}
|
||||
|
||||
// Write the original file size at the start
|
||||
UInt32 actualSize = sourceStream->GetPosition();
|
||||
outputStream.Rewind();
|
||||
outputStream.Skip(kMagicStringLen);
|
||||
outputStream.WriteSwap32(actualSize);
|
||||
|
||||
outputStream.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plSecureStream::FileEncrypt(const char* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = FileEncrypt(wFilename, key);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plSecureStream::FileEncrypt(const wchar* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
hsUNIXStream sIn;
|
||||
if (!sIn.Open(fileName))
|
||||
return false;
|
||||
|
||||
// Don't double encrypt any files
|
||||
if (ICheckMagicString(sIn.GetFILE()))
|
||||
{
|
||||
sIn.Close();
|
||||
return true;
|
||||
}
|
||||
sIn.Rewind();
|
||||
|
||||
plSecureStream sOut(false, key);
|
||||
bool wroteEncrypted = sOut.IWriteEncrypted(&sIn, L"crypt.dat");
|
||||
|
||||
sIn.Close();
|
||||
sOut.Close();
|
||||
|
||||
if (wroteEncrypted)
|
||||
{
|
||||
plFileUtils::RemoveFile(fileName);
|
||||
plFileUtils::FileMove(L"crypt.dat", fileName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plSecureStream::FileDecrypt(const char* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = FileDecrypt(wFilename, key);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plSecureStream::FileDecrypt(const wchar* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
plSecureStream sIn(false, key);
|
||||
if (!sIn.Open(fileName))
|
||||
return false;
|
||||
|
||||
hsUNIXStream sOut;
|
||||
if (!sOut.Open(L"crypt.dat", L"wb"))
|
||||
{
|
||||
sIn.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
|
||||
while (!sIn.AtEnd())
|
||||
{
|
||||
UInt32 numRead = sIn.Read(sizeof(buf), buf);
|
||||
sOut.Write(numRead, buf);
|
||||
}
|
||||
|
||||
sIn.Close();
|
||||
sOut.Close();
|
||||
|
||||
plFileUtils::RemoveFile(fileName);
|
||||
plFileUtils::FileMove(L"crypt.dat", fileName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plSecureStream::ICheckMagicString(HANDLE fp)
|
||||
{
|
||||
char magicString[kMagicStringLen+1];
|
||||
DWORD numBytesRead;
|
||||
ReadFile(fp, &magicString, kMagicStringLen, &numBytesRead, NULL);
|
||||
magicString[kMagicStringLen] = '\0';
|
||||
return (hsStrEQ(magicString, kMagicString) != 0);
|
||||
}
|
||||
|
||||
bool plSecureStream::IsSecureFile(const char* fileName)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
bool ret = IsSecureFile(wFilename);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool plSecureStream::IsSecureFile(const wchar* fileName)
|
||||
{
|
||||
HANDLE fp = INVALID_HANDLE_VALUE;
|
||||
fp = CreateFileW(fileName,
|
||||
GENERIC_READ, // open for reading
|
||||
0, // no one can open the file until we're done
|
||||
NULL, // default security
|
||||
OPEN_EXISTING, // only open existing files (no creation)
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file attributes
|
||||
NULL); // no template
|
||||
|
||||
if (fp == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
bool isEncrypted = ICheckMagicString(fp);
|
||||
|
||||
CloseHandle(fp);
|
||||
|
||||
return isEncrypted;
|
||||
}
|
||||
|
||||
hsStream* plSecureStream::OpenSecureFile(const char* fileName, const UInt32 flags /* = kRequireEncryption */, UInt32* key /* = nil */)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
hsStream* ret = OpenSecureFile(wFilename, flags, key);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsStream* plSecureStream::OpenSecureFile(const wchar* fileName, const UInt32 flags /* = kRequireEncryption */, UInt32* key /* = nil */)
|
||||
{
|
||||
bool requireEncryption = flags & kRequireEncryption;
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
requireEncryption = false;
|
||||
#endif
|
||||
|
||||
hsBool deleteOnExit = flags & kDeleteOnExit;
|
||||
bool isEncrypted = IsSecureFile(fileName);
|
||||
|
||||
hsStream* s = nil;
|
||||
if (isEncrypted)
|
||||
s = TRACKED_NEW plSecureStream(deleteOnExit, key);
|
||||
else if (!requireEncryption) // If this isn't an external release, let them use unencrypted data
|
||||
s = TRACKED_NEW hsUNIXStream;
|
||||
|
||||
if (s)
|
||||
s->Open(fileName, L"rb");
|
||||
return s;
|
||||
}
|
||||
|
||||
hsStream* plSecureStream::OpenSecureFileWrite(const char* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
wchar* wFilename = hsStringToWString(fileName);
|
||||
hsStream* ret = OpenSecureFileWrite(wFilename, key);
|
||||
delete [] wFilename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsStream* plSecureStream::OpenSecureFileWrite(const wchar* fileName, UInt32* key /* = nil */)
|
||||
{
|
||||
hsStream* s = nil;
|
||||
#ifdef PLASMA_EXTERNAL_RELEASE
|
||||
s = TRACKED_NEW plSecureStream(false, key);
|
||||
#else
|
||||
s = TRACKED_NEW hsUNIXStream;
|
||||
#endif
|
||||
|
||||
s->Open(fileName, L"wb");
|
||||
return s;
|
||||
}
|
127
Sources/Plasma/PubUtilLib/plFile/plSecureStream.h
Normal file
127
Sources/Plasma/PubUtilLib/plFile/plSecureStream.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*==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==*/
|
||||
#ifndef plSecureStream_h_inc
|
||||
#define plSecureStream_h_inc
|
||||
|
||||
#include "hsStream.h"
|
||||
#include <windows.h>
|
||||
|
||||
// A slightly more secure stream then plEncryptedStream in that it uses windows file functions
|
||||
// to prevent other processes from accessing the file it is working with. It also can be set
|
||||
// to download the file from a server into a temporary directory (with a mangled name) and
|
||||
// delete that file on close, thereby minimizing the chance of having that file examined or
|
||||
// edited.
|
||||
class plSecureStream: public hsStream
|
||||
{
|
||||
protected:
|
||||
HANDLE fRef;
|
||||
UInt32 fKey[4];
|
||||
|
||||
UInt32 fActualFileSize;
|
||||
|
||||
bool fBufferedStream;
|
||||
|
||||
hsStream* fRAMStream;
|
||||
|
||||
wchar* fWriteFileName;
|
||||
|
||||
enum OpenMode {kOpenRead, kOpenWrite, kOpenFail};
|
||||
OpenMode fOpenMode;
|
||||
|
||||
hsBool fDeleteOnExit;
|
||||
|
||||
void IBufferFile();
|
||||
|
||||
UInt32 IRead(UInt32 bytes, void* buffer);
|
||||
|
||||
void IEncipher(UInt32* const v, UInt32 n);
|
||||
void IDecipher(UInt32* const v, UInt32 n);
|
||||
|
||||
bool IWriteEncrypted(hsStream* sourceStream, const wchar* outputFile);
|
||||
|
||||
static bool ICheckMagicString(HANDLE fp);
|
||||
|
||||
public:
|
||||
plSecureStream(hsBool deleteOnExit = false, UInt32* key = nil); // uses default key if you don't pass one in
|
||||
~plSecureStream();
|
||||
|
||||
virtual hsBool Open(const char* name, const char* mode = "rb");
|
||||
virtual hsBool Open(const wchar* name, const wchar* mode = L"rb");
|
||||
virtual hsBool Close();
|
||||
|
||||
virtual UInt32 Read(UInt32 byteCount, void* buffer);
|
||||
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
|
||||
virtual hsBool AtEnd();
|
||||
virtual void Skip(UInt32 deltaByteCount);
|
||||
virtual void Rewind();
|
||||
virtual void FastFwd();
|
||||
virtual UInt32 GetEOF();
|
||||
|
||||
UInt32 GetActualFileSize() const {return fActualFileSize;}
|
||||
|
||||
static bool FileEncrypt(const char* fileName, UInt32* key = nil);
|
||||
static bool FileEncrypt(const wchar* fileName, UInt32* key = nil);
|
||||
static bool FileDecrypt(const char* fileName, UInt32* key = nil);
|
||||
static bool FileDecrypt(const wchar* fileName, UInt32* key = nil);
|
||||
|
||||
enum OpenSecureFileFlags
|
||||
{
|
||||
kRequireEncryption = 0x01,
|
||||
kDeleteOnExit = 0x02,
|
||||
};
|
||||
|
||||
static bool IsSecureFile(const char* fileName);
|
||||
static bool IsSecureFile(const wchar* fileName);
|
||||
|
||||
// Attempts to create a read-binary stream for the requested file (delete the stream
|
||||
// when you are done with it!)
|
||||
static hsStream* OpenSecureFile(const char* fileName, const UInt32 flags = kRequireEncryption, UInt32* key = nil);
|
||||
static hsStream* OpenSecureFile(const wchar* fileName, const UInt32 flags = kRequireEncryption, UInt32* key = nil);
|
||||
// Attempts to create a write-binary stream for the requested file (delete the stream
|
||||
// when you are done with it!)
|
||||
static hsStream* OpenSecureFileWrite(const char* fileName, UInt32* key = nil);
|
||||
static hsStream* OpenSecureFileWrite(const wchar* fileName, UInt32* key = nil);
|
||||
|
||||
static const UInt32 kDefaultKey[4]; // our default encryption key
|
||||
};
|
||||
|
||||
#endif // plSecureStream_h_inc
|
212
Sources/Plasma/PubUtilLib/plFile/plStreamSource.cpp
Normal file
212
Sources/Plasma/PubUtilLib/plFile/plStreamSource.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*==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 "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;
|
||||
}
|
84
Sources/Plasma/PubUtilLib/plFile/plStreamSource.h
Normal file
84
Sources/Plasma/PubUtilLib/plFile/plStreamSource.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*==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==*/
|
||||
#ifndef plStreamSource_h_inc
|
||||
#define plStreamSource_h_inc
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
// A class for holding and accessing file streams. The preloader will insert
|
||||
// files in here once they are loaded. In internal builds, if a requested file
|
||||
// is not found, it will be retrieved from disk.
|
||||
class plStreamSource
|
||||
{
|
||||
private:
|
||||
struct fileData
|
||||
{
|
||||
std::wstring fFilename; // includes path
|
||||
std::wstring fDir; // parent directory
|
||||
std::wstring fExt;
|
||||
hsStream* fStream; // we own this pointer, so clean it up
|
||||
};
|
||||
std::map<std::wstring, fileData> fFileData; // key is filename
|
||||
|
||||
void ICleanup(); // closes all file pointers and cleans up after itself
|
||||
void IBreakupFilename(std::wstring filename, std::wstring& dir, std::wstring& ext);
|
||||
|
||||
plStreamSource() {}
|
||||
public:
|
||||
~plStreamSource() {ICleanup();}
|
||||
|
||||
// Force a cleanup of all data (some apps need to get at those file again, and they can't while we have them open)
|
||||
void Cleanup() {ICleanup();}
|
||||
|
||||
// File access functions
|
||||
hsStream* GetFile(std::wstring filename); // internal builds will read from disk if it doesn't exist
|
||||
std::vector<std::wstring> GetListOfNames(std::wstring dir, std::wstring ext); // internal builds merge from disk
|
||||
|
||||
// For other classes to insert files (takes ownership of the stream if successful)
|
||||
bool InsertFile(std::wstring filename, hsStream* stream);
|
||||
|
||||
// Instance handling
|
||||
static plStreamSource* GetInstance();
|
||||
};
|
||||
|
||||
#endif // plStreamSource_h_inc
|
Reference in New Issue
Block a user