aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2010-04-23 15:14:00 +0000
committerMike Buland <eichlan@xagasoft.com>2010-04-23 15:14:00 +0000
commit801e7de1f85656746d832508baf4583907826420 (patch)
tree6e2639b6904ee8bcef2781420741124948c17f2c
parentd8a8c482b2f6b09ee8995b9563397a9b9bd135e8 (diff)
downloadlibbu++-801e7de1f85656746d832508baf4583907826420.tar.gz
libbu++-801e7de1f85656746d832508baf4583907826420.tar.bz2
libbu++-801e7de1f85656746d832508baf4583907826420.tar.xz
libbu++-801e7de1f85656746d832508baf4583907826420.zip
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.
-rw-r--r--src/cryptohash.cpp16
-rw-r--r--src/cryptohash.h1
-rw-r--r--src/csvwriter.cpp38
-rw-r--r--src/csvwriter.h2
-rw-r--r--src/list.h4
-rw-r--r--src/md5.cpp18
-rw-r--r--src/md5.h1
-rw-r--r--src/multiserver.cpp5
-rw-r--r--src/multiserver.h2
-rw-r--r--src/sha1.cpp216
-rw-r--r--src/sha1.h69
-rw-r--r--src/tests/sha1.cpp39
12 files changed, 262 insertions, 149 deletions
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 )
20 addData( sData.getStr(), sData.getSize() ); 20 addData( sData.getStr(), sData.getSize() );
21} 21}
22 22
23Bu::FString Bu::CryptoHash::getHexResult()
24{
25 Bu::FString sResult = getResult();
26 Bu::FString sRet( 2*sResult.getSize() );
27 static const char hex_tab[] = {"0123456789abcdef"};
28
29 int k = 0;
30 for( int i = 0; i < sResult.getSize(); i++ )
31 {
32 sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF];
33 sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF];
34 }
35
36 return sRet;
37}
38
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
26 virtual void addData( const Bu::FString &sData ); 26 virtual void addData( const Bu::FString &sData );
27 virtual FString getResult() = 0; 27 virtual FString getResult() = 0;
28 virtual void writeResult( Stream &sOut ) = 0; 28 virtual void writeResult( Stream &sOut ) = 0;
29 virtual Bu::FString getHexResult();
29 }; 30 };
30}; 31};
31 32
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()
34{ 34{
35} 35}
36 36
37void Bu::CsvWriter::writeLine( const StrArray &aStrs )
38{
39 Bu::FString sBuf;
40 for( StrArray::const_iterator i = aStrs.begin(); i; i++ )
41 {
42 if( i != aStrs.begin() )
43 sBuf += ",";
44 sBuf += sEncode( *i );
45 }
46 sBuf += "\n";
47
48 sOut.write( sBuf );
49}
50
37Bu::FString Bu::CsvWriter::encodeExcel( const Bu::FString &sIn ) 51Bu::FString Bu::CsvWriter::encodeExcel( const Bu::FString &sIn )
38{ 52{
39 return ""; 53 if( sIn.find('\"') )
54 {
55 Bu::FString sOut = "\"";
56 for( Bu::FString::const_iterator i = sIn.begin(); i; i++ )
57 {
58 if( *i == '\"' )
59 sOut += "\"\"";
60 else
61 sOut += *i;
62 }
63 return sOut;
64 }
65 return sIn;
40} 66}
41 67
42Bu::FString Bu::CsvWriter::encodeC( const Bu::FString &sIn ) 68Bu::FString Bu::CsvWriter::encodeC( const Bu::FString &sIn )
43{ 69{
44 return ""; 70 Bu::FString sOut = "";
71 for( Bu::FString::const_iterator i = sIn.begin(); i; i++ )
72 {
73 if( *i == ',' )
74 sOut += "\\,";
75 else
76 sOut += *i;
77 }
78 return sOut;
45} 79}
46 80
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
31 CsvWriter( Stream &sOut, EncodeSignal sEncode ); 31 CsvWriter( Stream &sOut, EncodeSignal sEncode );
32 virtual ~CsvWriter(); 32 virtual ~CsvWriter();
33 33
34 void writeLine( const StrArray &aStrs );
35
34 private: 36 private:
35 Stream &sOut; 37 Stream &sOut;
36 EncodeSignal sEncode; 38 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
871 */ 871 */
872 value &first() 872 value &first()
873 { 873 {
874 if( core->pFirst->pValue == NULL )
875 throw Bu::ExceptionBase("Attempt to read first element from empty list.");
874 _hardCopy(); 876 _hardCopy();
875 return *core->pFirst->pValue; 877 return *core->pFirst->pValue;
876 } 878 }
@@ -881,6 +883,8 @@ namespace Bu
881 */ 883 */
882 const value &first() const 884 const value &first() const
883 { 885 {
886 if( core->pFirst->pValue == NULL )
887 throw Bu::ExceptionBase("Attempt to read first element from empty list.");
884 return *core->pFirst->pValue; 888 return *core->pFirst->pValue;
885 } 889 }
886 890
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 )
98 sOut.write( lsum, 4*4 ); 98 sOut.write( lsum, 4*4 );
99} 99}
100 100
101Bu::FString Bu::Md5::getHexResult()
102{
103 static const char hex_tab[] = {"0123456789abcdef"};
104 char str[33];
105
106 long lsum[4];
107 compCap( lsum );
108
109 int k = 0;
110 for( int i = 0; i < 16; i++ )
111 {
112 str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8+4)) & 0xF];
113 str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8 )) & 0xF];
114 }
115
116 return Bu::FString( str, 32 );
117}
118
119void Bu::Md5::compCap( long *sumout ) 101void Bu::Md5::compCap( long *sumout )
120{ 102{
121 memcpy( sumout, sum, 4*4 ); 103 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
31 using Bu::CryptoHash::addData; 31 using Bu::CryptoHash::addData;
32 virtual FString getResult(); 32 virtual FString getResult();
33 virtual void writeResult( Bu::Stream &sOut ); 33 virtual void writeResult( Bu::Stream &sOut );
34 virtual FString getHexResult();
35 34
36 private: 35 private:
37 /** 36 /**
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()
48 Bu::Server::shutdown(); 48 Bu::Server::shutdown();
49} 49}
50 50
51void Bu::MultiServer::tick()
52{
53 Bu::Server::tick();
54}
55
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
47 47
48 void shutdown(); 48 void shutdown();
49 49
50 void tick();
51
50 private: 52 private:
51 Bu::Hash<int, Protocol *(*)()> hProtos; 53 Bu::Hash<int, Protocol *(*)()> hProtos;
52 }; 54 };
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 @@
5 * terms of the license contained in the file LICENSE. 5 * terms of the license contained in the file LICENSE.
6 */ 6 */
7 7
8#include <stdio.h>
9#include <string.h> 8#include <string.h>
10#include <stdlib.h> 9
10#include "bu/stream.h"
11 11
12#include "bu/sha1.h" 12#include "bu/sha1.h"
13 13
14Sha1::Sha1() : 14Bu::Sha1::Sha1() :
15 H0( 0x67452301 ), 15 uH0( 0x67452301 ),
16 H1( 0xefcdab89 ), 16 uH1( 0xefcdab89 ),
17 H2( 0x98badcfe ), 17 uH2( 0x98badcfe ),
18 H3( 0x10325476 ), 18 uH3( 0x10325476 ),
19 H4( 0xc3d2e1f0 ), 19 uH4( 0xc3d2e1f0 ),
20 unprocessedBytes( 0 ), 20 iUnprocessedBytes( 0 ),
21 size( 0 ) 21 uTotalBytes( 0 )
22{ 22{
23 reset();
23} 24}
24 25
25Sha1::~Sha1() 26Bu::Sha1::~Sha1()
26{ 27{
27} 28}
28 29
29void Sha1::process() 30void Bu::Sha1::reset()
30{ 31{
31 int t; 32 uH0 = 0x67452301;
32 uint32_t a, b, c, d, e, K, f, W[80]; 33 uH1 = 0xefcdab89;
33 34 uH2 = 0x98badcfe;
34 // starting values 35 uH3 = 0x10325476;
35 a = H0; 36 uH4 = 0xc3d2e1f0;
36 b = H1; 37 iUnprocessedBytes = 0;
37 c = H2; 38 uTotalBytes = 0;
38 d = H3; 39}
39 e = H4;
40
41 // copy and expand the message block
42 for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24)
43 +(bytes[t*4 + 1] << 16)
44 +(bytes[t*4 + 2] << 8)
45 + bytes[t*4 + 3];
46 for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
47
48 /* main loop */
49 uint32_t temp;
50 for( t = 0; t < 80; t++ )
51 {
52 if( t < 20 ) {
53 K = 0x5a827999;
54 f = (b & c) | ((~b) & d);
55 } else if( t < 40 ) {
56 K = 0x6ed9eba1;
57 f = b ^ c ^ d;
58 } else if( t < 60 ) {
59 K = 0x8f1bbcdc;
60 f = (b & c) | (b & d) | (c & d);
61 } else {
62 K = 0xca62c1d6;
63 f = b ^ c ^ d;
64 }
65 temp = lrot(a,5) + f + e + W[t] + K;
66 e = d;
67 d = c;
68 c = lrot(b,30);
69 b = a;
70 a = temp;
71 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
72 }
73
74 /* add variables */
75 H0 += a;
76 H1 += b;
77 H2 += c;
78 H3 += d;
79 H4 += e;
80 40
81 //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); 41void Bu::Sha1::setSalt( const Bu::FString & /*sSalt*/ )
82 /* all bytes have been processed */ 42{
83 unprocessedBytes = 0;
84} 43}
85 44
86void Sha1::update( const char* data, int num ) 45void Bu::Sha1::addData( const void *sDataRaw, int iSize )
87{ 46{
47 const unsigned char *sData = (const unsigned char *)sDataRaw;
88 // add these bytes to the running total 48 // add these bytes to the running total
89 size += num; 49 uTotalBytes += iSize;
90 50
91 // repeat until all data is processed 51 // repeat until all data is processed
92 while( num > 0 ) 52 while( iSize > 0 )
93 { 53 {
94 // number of bytes required to complete block 54 // number of bytes required to complete block
95 int needed = 64 - unprocessedBytes; 55 int iNeeded = 64 - iUnprocessedBytes;
96 56
97 // number of bytes to copy (use smaller of two) 57 // number of bytes to copy (use smaller of two)
98 int toCopy = (num < needed) ? num : needed; 58 int iToCopy = (iSize < iNeeded) ? iSize : iNeeded;
99 59
100 // Copy the bytes 60 // Copy the bytes
101 memcpy( bytes + unprocessedBytes, data, toCopy ); 61 memcpy( uBytes + iUnprocessedBytes, sData, iToCopy );
102 62
103 // Bytes have been copied 63 // Bytes have been copied
104 num -= toCopy; 64 iSize -= iToCopy;
105 data += toCopy; 65 sData += iToCopy;
106 unprocessedBytes += toCopy; 66 iUnprocessedBytes += iToCopy;
107 67
108 // there is a full block 68 // there is a full block
109 if( unprocessedBytes == 64 ) process(); 69 if( iUnprocessedBytes == 64 )
70 {
71 process();
72 }
110 } 73 }
111} 74}
112 75
113unsigned char* Sha1::getDigest() 76Bu::FString Bu::Sha1::getResult()
114{ 77{
115 // save the message size 78 // save the message size
116 uint32_t totalBitsL = size << 3; 79 uint32_t totalBitsL = uTotalBytes << 3;
117 uint32_t totalBitsH = size >> 29; 80 uint32_t totalBitsH = uTotalBytes >> 29;
118 81
119 // add 0x80 to the message 82 // add 0x80 to the message
120 update( "\x80", 1 ); 83 addData( "\x80", 1 );
121 84
122 unsigned char footer[64] = { 85 unsigned char footer[64] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -126,39 +89,102 @@ unsigned char* Sha1::getDigest()
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
127 90
128 // block has no room for 8-byte filesize, so finish it 91 // block has no room for 8-byte filesize, so finish it
129 if( unprocessedBytes > 56 ) 92 if( iUnprocessedBytes > 56 )
130 update( (char*)footer, 64 - unprocessedBytes); 93 addData( (char*)footer, 64 - iUnprocessedBytes);
131 94
132 // how many zeros do we need 95 // how many zeros do we need
133 int neededZeros = 56 - unprocessedBytes; 96 int iNeededZeros = 56 - iUnprocessedBytes;
134 97
135 // store file size (in bits) in big-endian format 98 // store file size (in bits) in big-endian format
136 toBigEndian( totalBitsH, footer + neededZeros ); 99 toBigEndian( totalBitsH, footer + iNeededZeros );
137 toBigEndian( totalBitsL, footer + neededZeros + 4 ); 100 toBigEndian( totalBitsL, footer + iNeededZeros + 4 );
138 101
139 // finish the final block 102 // finish the final block
140 update( (char*)footer, neededZeros + 8 ); 103 addData( (char*)footer, iNeededZeros + 8 );
104
105 Bu::FString sRet( 20 );
141 106
142 // allocate memory for the digest bytes 107 unsigned char *digest = (unsigned char *)sRet.getStr();
143 unsigned char* digest = new unsigned char[20];
144 108
145 // copy the digest bytes 109 // copy the digest bytes
146 toBigEndian( H0, digest ); 110 toBigEndian( uH0, digest );
147 toBigEndian( H1, digest + 4 ); 111 toBigEndian( uH1, digest + 4 );
148 toBigEndian( H2, digest + 8 ); 112 toBigEndian( uH2, digest + 8 );
149 toBigEndian( H3, digest + 12 ); 113 toBigEndian( uH3, digest + 12 );
150 toBigEndian( H4, digest + 16 ); 114 toBigEndian( uH4, digest + 16 );
151 115
152 // return the digest 116 // return the digest
153 return digest; 117 return sRet;
154} 118}
155 119
156uint32_t Sha1::lrot( uint32_t x, int bits ) 120void Bu::Sha1::writeResult( Bu::Stream &sOut )
121{
122 sOut.write( getResult() );
123}
124
125void Bu::Sha1::process()
126{
127 int t;
128 uint32_t a, b, c, d, e, K, f, W[80];
129
130 // starting values
131 a = uH0;
132 b = uH1;
133 c = uH2;
134 d = uH3;
135 e = uH4;
136
137 // copy and expand the message block
138 for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24)
139 +(uBytes[t*4 + 1] << 16)
140 +(uBytes[t*4 + 2] << 8)
141 + uBytes[t*4 + 3];
142 for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
143
144 /* main loop */
145 uint32_t temp;
146 for( t = 0; t < 80; t++ )
147 {
148 if( t < 20 ) {
149 K = 0x5a827999;
150 f = (b & c) | ((~b) & d);
151 } else if( t < 40 ) {
152 K = 0x6ed9eba1;
153 f = b ^ c ^ d;
154 } else if( t < 60 ) {
155 K = 0x8f1bbcdc;
156 f = (b & c) | (b & d) | (c & d);
157 } else {
158 K = 0xca62c1d6;
159 f = b ^ c ^ d;
160 }
161 temp = lrot(a,5) + f + e + W[t] + K;
162 e = d;
163 d = c;
164 c = lrot(b,30);
165 b = a;
166 a = temp;
167 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
168 }
169
170 /* add variables */
171 uH0 += a;
172 uH1 += b;
173 uH2 += c;
174 uH3 += d;
175 uH4 += e;
176
177 //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
178 /* all bytes have been processed */
179 iUnprocessedBytes = 0;
180}
181
182uint32_t Bu::Sha1::lrot( uint32_t x, int bits )
157{ 183{
158 return (x<<bits) | (x>>(32 - bits)); 184 return (x<<bits) | (x>>(32 - bits));
159}; 185}
160 186
161void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) 187void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte )
162{ 188{
163 byte[0] = (unsigned char)(num>>24); 189 byte[0] = (unsigned char)(num>>24);
164 byte[1] = (unsigned char)(num>>16); 190 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 @@
5 * terms of the license contained in the file LICENSE. 5 * terms of the license contained in the file LICENSE.
6 */ 6 */
7 7
8/* sha1.h
9
10Copyright (c) 2005 Michael D. Leonhard
11
12http://tamale.net/
13
14This file is licensed under the terms described in the
15accompanying LICENSE file.
16*/
17
18#ifndef SHA1_H 8#ifndef SHA1_H
19#define SHA1_H 9#define SHA1_H
20 10
21#include <stdint.h> 11#include <stdint.h>
12#include "bu/cryptohash.h"
22 13
23/** 14namespace Bu
24 * Calculates SHA-1 sums. This is based strongly on code from Michael D.
25 * Leonhard who released his code under the terms of the MIT license, thank you!
26 */
27class Sha1
28{ 15{
29public: 16 /**
30 Sha1(); 17 * Calculates SHA-1 sums. This is based strongly on code from Michael D.
31 ~Sha1(); 18 * Leonhard who released his code under the terms of the MIT license,
32 19 * thank you! Check out his website http://tamale.net he has a lot of
33 void update( const char* data, int num ); 20 * cool stuff there.
34 unsigned char* getDigest(); 21 */
35 22 class Sha1 : public CryptoHash
36 // utility methods 23 {
37 static uint32_t lrot( uint32_t x, int bits ); 24 public:
38 static void toBigEndian( uint32_t in, unsigned char* out ); 25 Sha1();
39 26 ~Sha1();
40private: 27
41 // fields 28 virtual void reset();
42 uint32_t H0, H1, H2, H3, H4; 29 virtual void setSalt( const Bu::FString &sSalt );
43 unsigned char bytes[64]; 30 virtual void addData( const void *sData, int iSize );
44 int unprocessedBytes; 31 virtual FString getResult();
45 uint32_t size; 32 virtual void writeResult( Stream &sOut );
46 void process(); 33
34 void update( const char* data, int num );
35 unsigned char* getDigest();
36
37 // utility methods
38
39 private:
40 static uint32_t lrot( uint32_t x, int bits );
41 static void toBigEndian( uint32_t in, unsigned char* out );
42 void process();
43
44 private:
45 uint32_t uH0, uH1, uH2, uH3, uH4;
46 unsigned char uBytes[64];
47 int iUnprocessedBytes;
48 uint32_t uTotalBytes;
49 };
47}; 50};
48 51
49#endif 52#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 @@
1/*
2 * Copyright (C) 2007-2010 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/sio.h"
9#include "bu/file.h"
10#include "bu/sha1.h"
11
12using namespace Bu;
13
14int main( int argc, char *argv[] )
15{
16 argv++, argc--;
17 for(; *argv; argv++ )
18 {
19 Bu::File fIn( *argv, Bu::File::Read );
20 Bu::Sha1 m;
21
22 char buf[100000];
23 for(;;)
24 {
25 int iRead = fIn.read( buf, 100000 );
26 m.addData( buf, iRead );
27 if( iRead < 100000 )
28 break;
29 }
30
31 Bu::FString sRes = m.getResult();
32 for( Bu::FString::iterator i = sRes.begin(); i; i++ )
33 {
34 sio << Fmt::hex(2,false) << (int)(unsigned char)(*i);
35 }
36 sio << " *" << *argv << sio.nl;
37 }
38}
39