From 801e7de1f85656746d832508baf4583907826420 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 23 Apr 2010 15:14:00 +0000 Subject: Minor updates to the List class, unchecked corner cases. The CsvWriter now writes csv. It understands both excel formatting and c-style, which I made up myself (it's just c-style escape sequences). Sha1 is converted to work with the CryptoHash API and it does indeed work. --- src/cryptohash.cpp | 16 ++++ src/cryptohash.h | 1 + src/csvwriter.cpp | 38 ++++++++- src/csvwriter.h | 2 + src/list.h | 4 + src/md5.cpp | 18 ----- src/md5.h | 1 - src/multiserver.cpp | 5 ++ src/multiserver.h | 2 + src/sha1.cpp | 216 +++++++++++++++++++++++++++++----------------------- src/sha1.h | 69 +++++++++-------- src/tests/sha1.cpp | 39 ++++++++++ 12 files changed, 262 insertions(+), 149 deletions(-) create mode 100644 src/tests/sha1.cpp diff --git a/src/cryptohash.cpp b/src/cryptohash.cpp index c3cb8b5..8aee415 100644 --- a/src/cryptohash.cpp +++ b/src/cryptohash.cpp @@ -20,3 +20,19 @@ void Bu::CryptoHash::addData( const Bu::FString &sData ) addData( sData.getStr(), sData.getSize() ); } +Bu::FString Bu::CryptoHash::getHexResult() +{ + Bu::FString sResult = getResult(); + Bu::FString sRet( 2*sResult.getSize() ); + static const char hex_tab[] = {"0123456789abcdef"}; + + int k = 0; + for( int i = 0; i < sResult.getSize(); i++ ) + { + sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; + sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; + } + + return sRet; +} + diff --git a/src/cryptohash.h b/src/cryptohash.h index df8cc57..5d83895 100644 --- a/src/cryptohash.h +++ b/src/cryptohash.h @@ -26,6 +26,7 @@ namespace Bu virtual void addData( const Bu::FString &sData ); virtual FString getResult() = 0; virtual void writeResult( Stream &sOut ) = 0; + virtual Bu::FString getHexResult(); }; }; diff --git a/src/csvwriter.cpp b/src/csvwriter.cpp index 59a471f..3e2816b 100644 --- a/src/csvwriter.cpp +++ b/src/csvwriter.cpp @@ -34,13 +34,47 @@ Bu::CsvWriter::~CsvWriter() { } +void Bu::CsvWriter::writeLine( const StrArray &aStrs ) +{ + Bu::FString sBuf; + for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) + { + if( i != aStrs.begin() ) + sBuf += ","; + sBuf += sEncode( *i ); + } + sBuf += "\n"; + + sOut.write( sBuf ); +} + Bu::FString Bu::CsvWriter::encodeExcel( const Bu::FString &sIn ) { - return ""; + if( sIn.find('\"') ) + { + Bu::FString sOut = "\""; + for( Bu::FString::const_iterator i = sIn.begin(); i; i++ ) + { + if( *i == '\"' ) + sOut += "\"\""; + else + sOut += *i; + } + return sOut; + } + return sIn; } Bu::FString Bu::CsvWriter::encodeC( const Bu::FString &sIn ) { - return ""; + Bu::FString sOut = ""; + for( Bu::FString::const_iterator i = sIn.begin(); i; i++ ) + { + if( *i == ',' ) + sOut += "\\,"; + else + sOut += *i; + } + return sOut; } diff --git a/src/csvwriter.h b/src/csvwriter.h index c69d250..289d25c 100644 --- a/src/csvwriter.h +++ b/src/csvwriter.h @@ -31,6 +31,8 @@ namespace Bu CsvWriter( Stream &sOut, EncodeSignal sEncode ); virtual ~CsvWriter(); + void writeLine( const StrArray &aStrs ); + private: Stream &sOut; EncodeSignal sEncode; diff --git a/src/list.h b/src/list.h index 6d2246e..3979b63 100644 --- a/src/list.h +++ b/src/list.h @@ -871,6 +871,8 @@ namespace Bu */ value &first() { + if( core->pFirst->pValue == NULL ) + throw Bu::ExceptionBase("Attempt to read first element from empty list."); _hardCopy(); return *core->pFirst->pValue; } @@ -881,6 +883,8 @@ namespace Bu */ const value &first() const { + if( core->pFirst->pValue == NULL ) + throw Bu::ExceptionBase("Attempt to read first element from empty list."); return *core->pFirst->pValue; } diff --git a/src/md5.cpp b/src/md5.cpp index cfb1e6e..abf4bfa 100644 --- a/src/md5.cpp +++ b/src/md5.cpp @@ -98,24 +98,6 @@ void Bu::Md5::writeResult( Bu::Stream &sOut ) sOut.write( lsum, 4*4 ); } -Bu::FString Bu::Md5::getHexResult() -{ - static const char hex_tab[] = {"0123456789abcdef"}; - char str[33]; - - long lsum[4]; - compCap( lsum ); - - int k = 0; - for( int i = 0; i < 16; i++ ) - { - str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8+4)) & 0xF]; - str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8 )) & 0xF]; - } - - return Bu::FString( str, 32 ); -} - void Bu::Md5::compCap( long *sumout ) { memcpy( sumout, sum, 4*4 ); diff --git a/src/md5.h b/src/md5.h index d4229d0..79b1d09 100644 --- a/src/md5.h +++ b/src/md5.h @@ -31,7 +31,6 @@ namespace Bu using Bu::CryptoHash::addData; virtual FString getResult(); virtual void writeResult( Bu::Stream &sOut ); - virtual FString getHexResult(); private: /** diff --git a/src/multiserver.cpp b/src/multiserver.cpp index dd2da3b..4eccde8 100644 --- a/src/multiserver.cpp +++ b/src/multiserver.cpp @@ -48,3 +48,8 @@ void Bu::MultiServer::shutdown() Bu::Server::shutdown(); } +void Bu::MultiServer::tick() +{ + Bu::Server::tick(); +} + diff --git a/src/multiserver.h b/src/multiserver.h index fc8305f..6b98c1d 100644 --- a/src/multiserver.h +++ b/src/multiserver.h @@ -47,6 +47,8 @@ namespace Bu void shutdown(); + void tick(); + private: Bu::Hash hProtos; }; diff --git a/src/sha1.cpp b/src/sha1.cpp index 80258d5..a206a78 100644 --- a/src/sha1.cpp +++ b/src/sha1.cpp @@ -5,119 +5,82 @@ * terms of the license contained in the file LICENSE. */ -#include #include -#include + +#include "bu/stream.h" #include "bu/sha1.h" -Sha1::Sha1() : - H0( 0x67452301 ), - H1( 0xefcdab89 ), - H2( 0x98badcfe ), - H3( 0x10325476 ), - H4( 0xc3d2e1f0 ), - unprocessedBytes( 0 ), - size( 0 ) +Bu::Sha1::Sha1() : + uH0( 0x67452301 ), + uH1( 0xefcdab89 ), + uH2( 0x98badcfe ), + uH3( 0x10325476 ), + uH4( 0xc3d2e1f0 ), + iUnprocessedBytes( 0 ), + uTotalBytes( 0 ) { + reset(); } -Sha1::~Sha1() +Bu::Sha1::~Sha1() { } -void Sha1::process() +void Bu::Sha1::reset() { - int t; - uint32_t a, b, c, d, e, K, f, W[80]; - - // starting values - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // copy and expand the message block - for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24) - +(bytes[t*4 + 1] << 16) - +(bytes[t*4 + 2] << 8) - + bytes[t*4 + 3]; - for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); - - /* main loop */ - uint32_t temp; - for( t = 0; t < 80; t++ ) - { - if( t < 20 ) { - K = 0x5a827999; - f = (b & c) | ((~b) & d); - } else if( t < 40 ) { - K = 0x6ed9eba1; - f = b ^ c ^ d; - } else if( t < 60 ) { - K = 0x8f1bbcdc; - f = (b & c) | (b & d) | (c & d); - } else { - K = 0xca62c1d6; - f = b ^ c ^ d; - } - temp = lrot(a,5) + f + e + W[t] + K; - e = d; - d = c; - c = lrot(b,30); - b = a; - a = temp; - //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); - } - - /* add variables */ - H0 += a; - H1 += b; - H2 += c; - H3 += d; - H4 += e; + uH0 = 0x67452301; + uH1 = 0xefcdab89; + uH2 = 0x98badcfe; + uH3 = 0x10325476; + uH4 = 0xc3d2e1f0; + iUnprocessedBytes = 0; + uTotalBytes = 0; +} - //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); - /* all bytes have been processed */ - unprocessedBytes = 0; +void Bu::Sha1::setSalt( const Bu::FString & /*sSalt*/ ) +{ } -void Sha1::update( const char* data, int num ) +void Bu::Sha1::addData( const void *sDataRaw, int iSize ) { + const unsigned char *sData = (const unsigned char *)sDataRaw; // add these bytes to the running total - size += num; + uTotalBytes += iSize; // repeat until all data is processed - while( num > 0 ) + while( iSize > 0 ) { // number of bytes required to complete block - int needed = 64 - unprocessedBytes; + int iNeeded = 64 - iUnprocessedBytes; // number of bytes to copy (use smaller of two) - int toCopy = (num < needed) ? num : needed; + int iToCopy = (iSize < iNeeded) ? iSize : iNeeded; // Copy the bytes - memcpy( bytes + unprocessedBytes, data, toCopy ); + memcpy( uBytes + iUnprocessedBytes, sData, iToCopy ); // Bytes have been copied - num -= toCopy; - data += toCopy; - unprocessedBytes += toCopy; + iSize -= iToCopy; + sData += iToCopy; + iUnprocessedBytes += iToCopy; // there is a full block - if( unprocessedBytes == 64 ) process(); + if( iUnprocessedBytes == 64 ) + { + process(); + } } } -unsigned char* Sha1::getDigest() +Bu::FString Bu::Sha1::getResult() { // save the message size - uint32_t totalBitsL = size << 3; - uint32_t totalBitsH = size >> 29; + uint32_t totalBitsL = uTotalBytes << 3; + uint32_t totalBitsH = uTotalBytes >> 29; // add 0x80 to the message - update( "\x80", 1 ); + addData( "\x80", 1 ); unsigned char footer[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -126,39 +89,102 @@ unsigned char* Sha1::getDigest() 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // block has no room for 8-byte filesize, so finish it - if( unprocessedBytes > 56 ) - update( (char*)footer, 64 - unprocessedBytes); + if( iUnprocessedBytes > 56 ) + addData( (char*)footer, 64 - iUnprocessedBytes); // how many zeros do we need - int neededZeros = 56 - unprocessedBytes; + int iNeededZeros = 56 - iUnprocessedBytes; // store file size (in bits) in big-endian format - toBigEndian( totalBitsH, footer + neededZeros ); - toBigEndian( totalBitsL, footer + neededZeros + 4 ); + toBigEndian( totalBitsH, footer + iNeededZeros ); + toBigEndian( totalBitsL, footer + iNeededZeros + 4 ); // finish the final block - update( (char*)footer, neededZeros + 8 ); + addData( (char*)footer, iNeededZeros + 8 ); + + Bu::FString sRet( 20 ); - // allocate memory for the digest bytes - unsigned char* digest = new unsigned char[20]; + unsigned char *digest = (unsigned char *)sRet.getStr(); // copy the digest bytes - toBigEndian( H0, digest ); - toBigEndian( H1, digest + 4 ); - toBigEndian( H2, digest + 8 ); - toBigEndian( H3, digest + 12 ); - toBigEndian( H4, digest + 16 ); + toBigEndian( uH0, digest ); + toBigEndian( uH1, digest + 4 ); + toBigEndian( uH2, digest + 8 ); + toBigEndian( uH3, digest + 12 ); + toBigEndian( uH4, digest + 16 ); // return the digest - return digest; + return sRet; } -uint32_t Sha1::lrot( uint32_t x, int bits ) +void Bu::Sha1::writeResult( Bu::Stream &sOut ) +{ + sOut.write( getResult() ); +} + +void Bu::Sha1::process() +{ + int t; + uint32_t a, b, c, d, e, K, f, W[80]; + + // starting values + a = uH0; + b = uH1; + c = uH2; + d = uH3; + e = uH4; + + // copy and expand the message block + for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24) + +(uBytes[t*4 + 1] << 16) + +(uBytes[t*4 + 2] << 8) + + uBytes[t*4 + 3]; + for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); + + /* main loop */ + uint32_t temp; + for( t = 0; t < 80; t++ ) + { + if( t < 20 ) { + K = 0x5a827999; + f = (b & c) | ((~b) & d); + } else if( t < 40 ) { + K = 0x6ed9eba1; + f = b ^ c ^ d; + } else if( t < 60 ) { + K = 0x8f1bbcdc; + f = (b & c) | (b & d) | (c & d); + } else { + K = 0xca62c1d6; + f = b ^ c ^ d; + } + temp = lrot(a,5) + f + e + W[t] + K; + e = d; + d = c; + c = lrot(b,30); + b = a; + a = temp; + //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); + } + + /* add variables */ + uH0 += a; + uH1 += b; + uH2 += c; + uH3 += d; + uH4 += e; + + //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); + /* all bytes have been processed */ + iUnprocessedBytes = 0; +} + +uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) { return (x<>(32 - bits)); -}; +} -void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) +void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) { byte[0] = (unsigned char)(num>>24); byte[1] = (unsigned char)(num>>16); diff --git a/src/sha1.h b/src/sha1.h index 184ba1e..6c6ee37 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -5,45 +5,48 @@ * terms of the license contained in the file LICENSE. */ -/* sha1.h - -Copyright (c) 2005 Michael D. Leonhard - -http://tamale.net/ - -This file is licensed under the terms described in the -accompanying LICENSE file. -*/ - #ifndef SHA1_H #define SHA1_H #include +#include "bu/cryptohash.h" -/** - * Calculates SHA-1 sums. This is based strongly on code from Michael D. - * Leonhard who released his code under the terms of the MIT license, thank you! - */ -class Sha1 +namespace Bu { -public: - Sha1(); - ~Sha1(); - - void update( const char* data, int num ); - unsigned char* getDigest(); - - // utility methods - static uint32_t lrot( uint32_t x, int bits ); - static void toBigEndian( uint32_t in, unsigned char* out ); - -private: - // fields - uint32_t H0, H1, H2, H3, H4; - unsigned char bytes[64]; - int unprocessedBytes; - uint32_t size; - void process(); + /** + * Calculates SHA-1 sums. This is based strongly on code from Michael D. + * Leonhard who released his code under the terms of the MIT license, + * thank you! Check out his website http://tamale.net he has a lot of + * cool stuff there. + */ + class Sha1 : public CryptoHash + { + public: + Sha1(); + ~Sha1(); + + virtual void reset(); + virtual void setSalt( const Bu::FString &sSalt ); + virtual void addData( const void *sData, int iSize ); + virtual FString getResult(); + virtual void writeResult( Stream &sOut ); + + void update( const char* data, int num ); + unsigned char* getDigest(); + + // utility methods + + private: + static uint32_t lrot( uint32_t x, int bits ); + static void toBigEndian( uint32_t in, unsigned char* out ); + void process(); + + private: + uint32_t uH0, uH1, uH2, uH3, uH4; + unsigned char uBytes[64]; + int iUnprocessedBytes; + uint32_t uTotalBytes; + }; }; #endif diff --git a/src/tests/sha1.cpp b/src/tests/sha1.cpp new file mode 100644 index 0000000..b1c798a --- /dev/null +++ b/src/tests/sha1.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2010 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/sio.h" +#include "bu/file.h" +#include "bu/sha1.h" + +using namespace Bu; + +int main( int argc, char *argv[] ) +{ + argv++, argc--; + for(; *argv; argv++ ) + { + Bu::File fIn( *argv, Bu::File::Read ); + Bu::Sha1 m; + + char buf[100000]; + for(;;) + { + int iRead = fIn.read( buf, 100000 ); + m.addData( buf, iRead ); + if( iRead < 100000 ) + break; + } + + Bu::FString sRes = m.getResult(); + for( Bu::FString::iterator i = sRes.begin(); i; i++ ) + { + sio << Fmt::hex(2,false) << (int)(unsigned char)(*i); + } + sio << " *" << *argv << sio.nl; + } +} + -- cgit v1.2.3