174 lines
4.8 KiB
C++
174 lines
4.8 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "filesystem/io_crypto.h"
|
|
|
|
using namespace GS::IO;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
uint Crypto::GetCaps() const
|
|
{ return wrapped_io->GetCaps(); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Crypto::Encrypt(GS::Array <char> &data)
|
|
{
|
|
size_t len = key.Len();
|
|
for (size_t n = 0; n < data.GetSize(); ++n)
|
|
data[(int)n] = data[(int)n] ^ key[(int)(n % len)];
|
|
}
|
|
void Crypto::Decrypt(GS::Array <char> &data)
|
|
{
|
|
size_t len = key.Len();
|
|
for (size_t n = 0; n < data.GetSize(); ++n)
|
|
data[(int)n] = data[(int)n] ^ key[(int)(n % len)];
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Handle *Crypto::Open(const char *path, Mode mode)
|
|
{
|
|
/*
|
|
When opening a file in read mode, the wrapped io file is decrypted and
|
|
stored in the cached io file system for further access.
|
|
When opening a file in write mode, the file is first created in clear
|
|
on the cached io then encrypted and committed to the wrapped io.
|
|
*/
|
|
Handle *h = NULL;
|
|
|
|
switch (mode)
|
|
{
|
|
case ModeRead:
|
|
{
|
|
// Load wrapped IO file.
|
|
AutoPtr <Handle> _h(wrapped_io->Open(path, mode));
|
|
if (_h.IsNull())
|
|
break;
|
|
|
|
size_t size = _h->GetSize();
|
|
Array <char> data(size);
|
|
if (data.IsNull())
|
|
break;
|
|
if (_h->Read(data.c_ptr(), size) != size)
|
|
break;
|
|
|
|
// Decrypt buffer.
|
|
Decrypt(data);
|
|
|
|
// Write decrypted content to cache IO.
|
|
if ((h = cache_io->Open(path, ModeWrite)) != NULL)
|
|
h->Write(data.c_ptr(), size);
|
|
_safe_delete(h);
|
|
|
|
h = cache_io->Open(path, mode);
|
|
}
|
|
break;
|
|
|
|
case ModeWrite:
|
|
h = cache_io->Open(path, mode);
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
return h ? new CryptoHandle(this, h, path, mode) : NULL;
|
|
}
|
|
void Crypto::Close(Handle *_h)
|
|
{
|
|
if (CryptoHandle *h = (CryptoHandle *)_h)
|
|
{
|
|
h->cached_h = NULL;
|
|
|
|
switch (h->io_mode)
|
|
{
|
|
case ModeRead:
|
|
cache_io->Delete(h->path);
|
|
break;
|
|
|
|
case ModeWrite:
|
|
{
|
|
// Retrieve the whole cached file content and drop it from the cache IO.
|
|
h->cached_h = cache_io->Open(h->path);
|
|
|
|
size_t size = h->cached_h->GetSize();
|
|
Array <char> data(size);
|
|
|
|
if (data.IsValid())
|
|
h->cached_h->Read(data.c_ptr(), size);
|
|
|
|
h->cached_h = NULL;
|
|
cache_io->Delete(h->path);
|
|
|
|
// Encrypt buffer.
|
|
Encrypt(data);
|
|
|
|
// Commit file to the wrapped IO.
|
|
AutoPtr <Handle> _h(wrapped_io->Open(h->path, ModeWrite));
|
|
if (_h.IsValid())
|
|
_h->Write(data.c_ptr(), size);
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Crypto::Delete(const char *path)
|
|
{ return wrapped_io->Delete(path); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
size_t Crypto::Tell(Handle *_h)
|
|
{
|
|
if (CryptoHandle *h = (CryptoHandle *)_h)
|
|
return h->cached_h->Tell();
|
|
return (size_t)-1;
|
|
}
|
|
size_t Crypto::Seek(Handle *_h, ptrdiff_t offset, SeekRef seek)
|
|
{
|
|
if (CryptoHandle *h = (CryptoHandle *)_h)
|
|
return h->cached_h->Seek(offset, seek);
|
|
return (size_t)-1;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
size_t Crypto::Read(Handle *_h, void *p, size_t s)
|
|
{
|
|
if (CryptoHandle *h = (CryptoHandle *)_h)
|
|
return h->cached_h->Read(p, s);
|
|
return 0;
|
|
}
|
|
size_t Crypto::Write(Handle *_h, const void *p, size_t s)
|
|
{
|
|
if (CryptoHandle *h = (CryptoHandle *)_h)
|
|
return h->cached_h->Write(p, s);
|
|
return 0;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Crypto::MkDir(const char *path)
|
|
{ return wrapped_io->MkDir(path); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
Crypto::Crypto(Base *_io, const char *_key) : wrapped_io(_io)
|
|
{
|
|
cache_io = new Memory;
|
|
key = _key;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
CryptoHandle::CryptoHandle(Base *io, Handle *h, const char *_path, Mode mode) : Handle(io), cached_h(h), path(_path), io_mode(mode)
|
|
{}
|
|
CryptoHandle::~CryptoHandle()
|
|
{ GetIOSystem()->Close(this); }
|
|
//------------------------------------------------------------------------------
|