mirror of
https://github.com/vgough/encfs.git
synced 2024-11-29 03:15:07 +01:00
254 lines
5.4 KiB
C++
254 lines
5.4 KiB
C++
|
/*****************************************************************************
|
||
|
* Author: Valient Gough <vgough@pobox.com>
|
||
|
*
|
||
|
*****************************************************************************
|
||
|
* Copyright (c) 2004, Valient Gough
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||
|
* for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "base/ConfigVar.h"
|
||
|
#include "base/Error.h"
|
||
|
|
||
|
#include <glog/logging.h>
|
||
|
#include <cstring>
|
||
|
|
||
|
#ifndef MIN
|
||
|
inline int MIN(int a, int b)
|
||
|
{
|
||
|
return (a < b) ? a : b;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
ConfigVar::ConfigVar()
|
||
|
: pd( new ConfigVarData )
|
||
|
{
|
||
|
pd->offset = 0;
|
||
|
}
|
||
|
|
||
|
ConfigVar::ConfigVar(const std::string &buf)
|
||
|
: pd( new ConfigVarData )
|
||
|
{
|
||
|
pd->buffer = buf;
|
||
|
pd->offset = 0;
|
||
|
}
|
||
|
|
||
|
ConfigVar::ConfigVar(const ConfigVar &src)
|
||
|
{
|
||
|
pd = src.pd;
|
||
|
}
|
||
|
|
||
|
ConfigVar::~ConfigVar()
|
||
|
{
|
||
|
pd.reset();
|
||
|
}
|
||
|
|
||
|
ConfigVar & ConfigVar::operator = (const ConfigVar &src)
|
||
|
{
|
||
|
if(src.pd == pd)
|
||
|
return *this;
|
||
|
else
|
||
|
pd = src.pd;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
void ConfigVar::resetOffset()
|
||
|
{
|
||
|
pd->offset = 0;
|
||
|
}
|
||
|
|
||
|
int ConfigVar::read(unsigned char *buffer_, int bytes) const
|
||
|
{
|
||
|
int toCopy = MIN( bytes, pd->buffer.size() - pd->offset );
|
||
|
|
||
|
if(toCopy > 0)
|
||
|
memcpy( buffer_, pd->buffer.data() + pd->offset, toCopy );
|
||
|
|
||
|
pd->offset += toCopy;
|
||
|
|
||
|
return toCopy;
|
||
|
}
|
||
|
|
||
|
int ConfigVar::write(const unsigned char *data, int bytes)
|
||
|
{
|
||
|
if(pd->buffer.size() == (unsigned int)pd->offset)
|
||
|
{
|
||
|
pd->buffer.append( (const char *)data, bytes );
|
||
|
} else
|
||
|
{
|
||
|
pd->buffer.insert( pd->offset, (const char *)data, bytes );
|
||
|
}
|
||
|
|
||
|
pd->offset += bytes;
|
||
|
|
||
|
return bytes;
|
||
|
}
|
||
|
|
||
|
int ConfigVar::size() const
|
||
|
{
|
||
|
return pd->buffer.size();
|
||
|
}
|
||
|
|
||
|
const char *ConfigVar::buffer() const
|
||
|
{
|
||
|
return pd->buffer.data();
|
||
|
}
|
||
|
|
||
|
int ConfigVar::at() const
|
||
|
{
|
||
|
return pd->offset;
|
||
|
}
|
||
|
|
||
|
void ConfigVar::writeString(const char *data, int bytes)
|
||
|
{
|
||
|
writeInt( bytes );
|
||
|
write( (const unsigned char *)data, bytes );
|
||
|
}
|
||
|
|
||
|
|
||
|
// convert integer to BER encoded integer
|
||
|
void ConfigVar::writeInt(int val)
|
||
|
{
|
||
|
// we can represent 7 bits per char output, so a 32bit number may take up
|
||
|
// to 5 bytes.
|
||
|
// first byte: 0x0000007f 0111,1111
|
||
|
// second byte: 0x00003f80 0011,1111 1000,0000
|
||
|
// third byte: 0x001fb000 0000,0000 0001,1111 1100,0000 0000,0000
|
||
|
// fourth byte: 0x0fe00000 0000,1111 1110,0000
|
||
|
// fifth byte: 0xf0000000 1111,0000
|
||
|
unsigned char digit[5];
|
||
|
|
||
|
digit[4] = (unsigned char)((val & 0x0000007f));
|
||
|
digit[3] = 0x80 | (unsigned char)((val & 0x00003f80) >> 7);
|
||
|
digit[2] = 0x80 | (unsigned char)((val & 0x001fc000) >> 14);
|
||
|
digit[1] = 0x80 | (unsigned char)((val & 0x0fe00000) >> 21);
|
||
|
digit[0] = 0x80 | (unsigned char)((val & 0xf0000000) >> 28);
|
||
|
|
||
|
// find the starting point - we only need to output starting at the most
|
||
|
// significant non-zero digit..
|
||
|
int start = 0;
|
||
|
while(digit[start] == 0x80)
|
||
|
++start;
|
||
|
|
||
|
write( digit + start, 5-start );
|
||
|
}
|
||
|
|
||
|
int ConfigVar::readInt() const
|
||
|
{
|
||
|
const unsigned char * buf = (const unsigned char *)buffer();
|
||
|
int bytes = this->size();
|
||
|
int offset = at();
|
||
|
int value = 0;
|
||
|
bool highBitSet;
|
||
|
|
||
|
rAssert( offset < bytes );
|
||
|
|
||
|
do
|
||
|
{
|
||
|
unsigned char tmp = buf[offset++];
|
||
|
highBitSet = tmp & 0x80;
|
||
|
|
||
|
value = (value << 7) | (int)(tmp & 0x7f);
|
||
|
} while(highBitSet && offset < bytes);
|
||
|
|
||
|
pd->offset = offset;
|
||
|
|
||
|
// should never end up with a negative number..
|
||
|
rAssert( value >= 0 );
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
int ConfigVar::readInt( int defaultValue ) const
|
||
|
{
|
||
|
int bytes = this->size();
|
||
|
int offset = at();
|
||
|
|
||
|
if(offset >= bytes)
|
||
|
return defaultValue;
|
||
|
else
|
||
|
return readInt();
|
||
|
}
|
||
|
|
||
|
bool ConfigVar::readBool( bool defaultValue ) const
|
||
|
{
|
||
|
int tmp = readInt( defaultValue ? 1 : 0 );
|
||
|
return (tmp != 0);
|
||
|
}
|
||
|
|
||
|
ConfigVar & operator << (ConfigVar &src, bool value)
|
||
|
{
|
||
|
src.writeInt( value ? 1 : 0 );
|
||
|
return src;
|
||
|
}
|
||
|
|
||
|
ConfigVar & operator << (ConfigVar &src, int var)
|
||
|
{
|
||
|
src.writeInt( var );
|
||
|
return src;
|
||
|
}
|
||
|
|
||
|
ConfigVar & operator << (ConfigVar &src, const std::string &str)
|
||
|
{
|
||
|
src.writeString( str.data(), str.length() );
|
||
|
return src;
|
||
|
}
|
||
|
|
||
|
const ConfigVar & operator >> (const ConfigVar &src, bool &result)
|
||
|
{
|
||
|
int tmp = src.readInt();
|
||
|
result = (tmp != 0);
|
||
|
return src;
|
||
|
}
|
||
|
|
||
|
const ConfigVar & operator >> (const ConfigVar &src, int &result)
|
||
|
{
|
||
|
result = src.readInt();
|
||
|
return src;
|
||
|
}
|
||
|
|
||
|
const ConfigVar & operator >> (const ConfigVar &src, std::string &result)
|
||
|
{
|
||
|
int length = src.readInt();
|
||
|
LOG_IF(WARNING, length <= 0) << "Invalid config length " << length;
|
||
|
|
||
|
int readLen;
|
||
|
|
||
|
unsigned char tmpBuf[32];
|
||
|
if(length > (int)sizeof(tmpBuf))
|
||
|
{
|
||
|
unsigned char *ptr = new unsigned char[length];
|
||
|
readLen = src.read( ptr, length );
|
||
|
result.assign( (char*)ptr, length );
|
||
|
delete[] ptr;
|
||
|
} else
|
||
|
{
|
||
|
readLen = src.read( tmpBuf, length );
|
||
|
result.assign( (char*)tmpBuf, length );
|
||
|
}
|
||
|
|
||
|
if(readLen != length)
|
||
|
{
|
||
|
VLOG(1) << "string encoded as size " << length
|
||
|
<< " bytes, read " << readLen;
|
||
|
}
|
||
|
|
||
|
rAssert(readLen == length);
|
||
|
|
||
|
return src;
|
||
|
}
|
||
|
|