00001 /* 00002 * wxChecksums 00003 * Written by Julien Couot. 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 */ 00019 00020 /** 00021 * \file checksumutil.cpp 00022 * Utility classes to compute and verify the checksums. 00023 */ 00024 00025 00026 //--------------------------------------------------------------------------- 00027 // For compilers that support precompilation, includes "wx.h". 00028 #include <wx/wxprec.h> 00029 00030 #ifdef __BORLANDC__ 00031 #pragma hdrstop 00032 #endif 00033 00034 #ifndef WX_PRECOMP 00035 // Include your minimal set of headers here, or wx.h 00036 #include <wx/wx.h> 00037 #endif 00038 00039 #include "checksumutil.hpp" 00040 #include "appprefs.hpp" 00041 #include "comdefs.hpp" 00042 00043 #include "compat.hpp" 00044 //--------------------------------------------------------------------------- 00045 00046 00047 /// The C++ standard namespace. 00048 using namespace std; 00049 00050 00051 //########################################################################### 00052 // ChecksumCalculator members 00053 //########################################################################### 00054 00055 /** 00056 * Default constructor. 00057 */ 00058 ChecksumCalculator::ChecksumCalculator() 00059 { 00060 checksumCalc.Add(NULL); 00061 checksumCalc.Shrink(); 00062 //setChecksum(NULL); 00063 setChecksumProgress(NULL); 00064 setBufferSize(512); 00065 } 00066 //--------------------------------------------------------------------------- 00067 00068 00069 /** 00070 * Constructor with a checksum instance to use and an optional progress handler. 00071 * 00072 * @param checksum Adress of a Checksum instance class to use for calculating the checksums. 00073 * @param progressHandler Adress of a ChecksumProgress instance class to show the progress (could be <CODE>NULL</CODE>). 00074 */ 00075 ChecksumCalculator::ChecksumCalculator(Checksum* checksum, ChecksumProgress* progressHandler) 00076 { 00077 checksumCalc.Add(checksum); 00078 checksumCalc.Shrink(); 00079 //setChecksum(checksum); 00080 setChecksumProgress(progressHandler); 00081 setBufferSize(512); 00082 } 00083 //--------------------------------------------------------------------------- 00084 00085 00086 /** 00087 * Gets the size of the buffer to use for reading in the input stream. 00088 * 00089 * @return The size of buffer to use for reading in the input stream. 00090 */ 00091 size_t ChecksumCalculator::getBufferSize() const 00092 { 00093 return bufferSize; 00094 } 00095 //--------------------------------------------------------------------------- 00096 00097 00098 /** 00099 * Sets the size of the buffer to use for reading in the input stream. 00100 * 00101 * @param bufSize The new size of the buffer to use for reading in the input stream. 00102 * @return The old size of the buffer to use for reading in the input stream. 00103 */ 00104 size_t ChecksumCalculator::setBufferSize(const size_t bufSize) 00105 { 00106 size_t old = bufferSize; 00107 bufferSize = bufSize; 00108 return old; 00109 } 00110 //--------------------------------------------------------------------------- 00111 00112 00113 /** 00114 * Gets the checksum's instance use to calculate the checksums. 00115 * 00116 * @return The checksum's instance use to calculate the checksums. 00117 */ 00118 Checksum* ChecksumCalculator::getChecksum() const 00119 { 00120 return checksumCalc[0]; 00121 } 00122 //--------------------------------------------------------------------------- 00123 00124 00125 /** 00126 * Sets the checksum's instance use to calculate the checksums. 00127 * 00128 * @param checksum The checksum's instance which will be used to calculate the checksums. 00129 * @return The old checksum's instance use to calculate the checksums. 00130 */ 00131 Checksum* ChecksumCalculator::setChecksum(Checksum* checksum) 00132 { 00133 Checksum* old = getChecksum(); 00134 checksumCalc[0] = checksum; 00135 return old; 00136 } 00137 //--------------------------------------------------------------------------- 00138 00139 00140 /** 00141 * Gets the progress handler used to show the progression. 00142 * 00143 * @return The progress handler used to show the progression. 00144 */ 00145 ChecksumProgress* ChecksumCalculator::getChecksumProgress() const 00146 { 00147 return progress; 00148 } 00149 //--------------------------------------------------------------------------- 00150 00151 00152 /** 00153 * Sets the progress handler used to show the progression. 00154 * 00155 * @param progressHandler The new progress handler which wiil be used to show the progression. 00156 * @return The old progress handler used to show the progression. 00157 */ 00158 ChecksumProgress* ChecksumCalculator::setChecksumProgress(ChecksumProgress* progressHandler) 00159 { 00160 ChecksumProgress* old = getChecksumProgress(); 00161 progress = progressHandler; 00162 return old; 00163 } 00164 //--------------------------------------------------------------------------- 00165 00166 00167 /** 00168 * Calculates the checksum from the given stream. 00169 * 00170 * @param in Input stream from which the data will be extracted to 00171 * compute the checksum. The data are extracted until the end 00172 * of the stream is reached. 00173 * @param sumValue The calculated value of the checksum from the input stream. 00174 * @return <UL> 00175 * <LI><CODE>Ok</CODE> if the checksum has been successfully calculated.</Li> 00176 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00177 * <LI><CODE>Canceled</CODE> if the user has canceled the calculation.</LI> 00178 * </UL> 00179 */ 00180 ChecksumCalculator::State ChecksumCalculator::calculate(wxInputStream& in, wxString& sumValue) 00181 { 00182 wxArrayString sumValues; 00183 State res = calculate(in, checksumCalc, sumValues); 00184 if (!sumValues.IsEmpty()) 00185 sumValue = sumValues[0]; 00186 return res; 00187 } 00188 //--------------------------------------------------------------------------- 00189 00190 00191 /** 00192 * Calculates the checksums from the given stream. 00193 * 00194 * @param in Input stream from which the data will be extracted to 00195 * compute the checksum. The data are extracted until the end 00196 * of the stream is reached. 00197 * @param checksums Array of checksums to calculate. 00198 * @param sumValues The calculated values of the checksums from the input 00199 * stream. The array is erased first before adding results. 00200 * On success <CODE>ArrayChecksum.GetCount() == sumValues.GetCount()</CODE>, 00201 * on failure, <CODE>sumValues</CODE> should be empty. 00202 * @return <UL> 00203 * <LI><CODE>Ok</CODE> if the checksum has been successfully calculated.</Li> 00204 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00205 * <LI><CODE>Canceled</CODE> if the user has canceled the calculation.</LI> 00206 * </UL> 00207 */ 00208 ChecksumCalculator::State ChecksumCalculator::calculate(wxInputStream& in, 00209 const ArrayChecksum& checksums, 00210 wxArrayString& sumValues) 00211 { 00212 // Check if the input stream is valid. 00213 if (!in.IsOk()) 00214 return ReadError; 00215 00216 // Check if at least a checksum instance is OK. 00217 bool aInstanceOK = false; 00218 size_t i = 0; 00219 size_t s = checksums.GetCount(); 00220 while (!aInstanceOK && i < s) 00221 if (checksums[i] != NULL) 00222 aInstanceOK = true; 00223 else 00224 i++; 00225 if (!aInstanceOK) 00226 return ReadError; 00227 00228 // Initializes the buffer. 00229 const size_t bufSize = getBufferSize(); 00230 wxByte* buff = new wxByte[bufSize]; 00231 00232 // Calculating the checksum. 00233 ChecksumProgress* p = getChecksumProgress(); 00234 bool canceled = false; 00235 size_t read; 00236 wxStreamError lastError = wxSTREAM_NO_ERROR; 00237 s = checksums.GetCount(); 00238 for (i = 0; i < s; i++) 00239 if (checksums[i] != NULL) 00240 checksums[i]->reset(); 00241 while (!canceled && !in.Eof() && lastError == wxSTREAM_NO_ERROR) 00242 { 00243 in.Read(buff, bufSize); 00244 read = in.LastRead(); 00245 if (read > 0 && read <= bufSize) 00246 { 00247 for (i = 0; i < s; i++) 00248 if (checksums[i] != NULL) 00249 checksums[i]->update(buff, read); 00250 if (p != NULL) 00251 p->update(read, canceled); 00252 } 00253 lastError = in.GetLastError(); 00254 } 00255 00256 // Cleans-up the memory 00257 delete[] buff; 00258 00259 if (canceled) 00260 return CanceledByUser; 00261 00262 if (lastError != wxSTREAM_NO_ERROR && lastError != wxSTREAM_EOF) 00263 return ReadError; 00264 00265 sumValues.Empty(); 00266 for (i = 0; i < s; i++) 00267 if (checksums[i] != NULL) 00268 sumValues.Add(checksums[i]->getValue()); 00269 else 00270 sumValues.Add(wxEmptyString); 00271 00272 return Ok; 00273 } 00274 //--------------------------------------------------------------------------- 00275 00276 00277 /** 00278 * Checks the checksum from the given stream. 00279 * 00280 * @param in Input stream from which the data will be extracted to 00281 * compute the checksum. The data are extracted until the end 00282 * of the stream is reached. 00283 * @param value The value of the checksum which will be compared with the 00284 * value that will be calculated. 00285 * @return <UL> 00286 * <LI><CODE>Ok</CODE> if the checksum has been successfully 00287 * calculated and if the two sums are equals.</LI> 00288 * <LI><CODE>Invalid</CODE> if the checksum has been successfully 00289 * calculated and if the two sums are not equals.</LI> 00290 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00291 * <LI><CODE>Canceled</CODE> if the user has canceled the calculation.</LI> 00292 * </UL> 00293 */ 00294 ChecksumCalculator::State ChecksumCalculator::check(wxInputStream& in, const wxString& value) 00295 { 00296 wxString calcSum; 00297 00298 State res = calculate(in, calcSum); 00299 if (res == Ok) 00300 { 00301 if (calcSum.CmpNoCase(value) == 0) 00302 return Ok; 00303 else 00304 return Invalid; 00305 } 00306 00307 return res; 00308 } 00309 //--------------------------------------------------------------------------- 00310 00311 00312 00313 00314 //########################################################################### 00315 // ChecksumFileCalculator members 00316 //########################################################################### 00317 00318 00319 /** 00320 * Default constructor. 00321 */ 00322 ChecksumFileCalculator::ChecksumFileCalculator() : ChecksumCalculator() 00323 { 00324 initBufferSize(); 00325 } 00326 //--------------------------------------------------------------------------- 00327 00328 00329 /** 00330 * Constructor with a checksum instance to use and an optional progress handler. 00331 * 00332 * @param checksum Adress of a Checksum instance class to use for calculating the checksums. 00333 * @param progressHandler Adress of a ChecksumProgress instance class to show the progress (could be <CODE>NULL</CODE>). 00334 */ 00335 ChecksumFileCalculator::ChecksumFileCalculator(Checksum* checksum, 00336 ChecksumProgress* progressHandler) : 00337 ChecksumCalculator(checksum, progressHandler) 00338 { 00339 initBufferSize(); 00340 } 00341 //--------------------------------------------------------------------------- 00342 00343 00344 /** 00345 * Initializes the buffer size for reading files. 00346 */ 00347 void ChecksumFileCalculator::initBufferSize() 00348 { 00349 size_t buffsize = AppPrefs::get()->readLong(prENGINE_READ_BUFFER); // buffer length 00350 if (buffsize <= 0 || buffsize > MAX_BUFF_SIZE) 00351 // Sets a reasonable value for the buffer. 00352 buffsize = DEF_BUFF_SIZE; 00353 setBufferSize(buffsize); 00354 } 00355 //--------------------------------------------------------------------------- 00356 00357 00358 /** 00359 * Gets a wxFileInputStream for reading the file. 00360 * 00361 * @param fileName Name of the file from which the input stream will be get. 00362 * @param state After the returning the value of this parameter can be: 00363 * <UL> 00364 * <LI><CODE>Ok</CODE> if the input stream has been 00365 * successfully created.</LI> 00366 * <LI><CODE>FileNotFound</CODE> if the file can't be 00367 * found.</LI> 00368 * <LI><CODE>CantOpenFile</CODE> if the file exists, but 00369 * can't be opened.</LI> 00370 * <LI><CODE>Canceled</CODE> if the user has canceled the 00371 * calculation.</LI> 00372 * </UL> 00373 * @return A pointer to the input created from the file name or 00374 * <CODE>NULL</CODE> if an error has occured. The caller is responsible 00375 * of freeing the memory with the <CODE>delete</CODE> operator. 00376 */ 00377 wxFileInputStream* ChecksumFileCalculator::getFileInputStream(const wxString& fileName, State& state) 00378 { 00379 wxFileInputStream* in = new wxFileInputStream(fileName); 00380 if (!in->Ok() || !in->IsOk()) 00381 { 00382 delete in; 00383 if (::wxFileExists(fileName)) 00384 state = CantOpenFile; 00385 else 00386 state = FileNotFound; 00387 return (wxFileInputStream*)NULL; 00388 } 00389 else 00390 { 00391 state = Ok; 00392 return in; 00393 } 00394 } 00395 //--------------------------------------------------------------------------- 00396 00397 00398 /** 00399 * Calculates the checksum from the given file. 00400 * 00401 * @param fileName Name of the file from which the data will be extracted to 00402 * compute the checksum. The data are extracted until the end 00403 * of the file is reached. 00404 * @param sumValue The calculated value of the checksum from the input stream. 00405 * @return <UL> 00406 * <LI><CODE>Ok</CODE> if the checksum has been successfully calculated.</Li> 00407 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00408 * <LI><CODE>FileNotFound</CODE> if the file doesn't exist.</LI> 00409 * <LI><CODE>CantOpenFile</CODE> if the file can't be opened.</LI> 00410 * <LI><CODE>Canceled</CODE> if the user has canceled the calculation.</LI> 00411 * </UL> 00412 */ 00413 ChecksumFileCalculator::State ChecksumFileCalculator::calculate(const wxString& fileName, wxString& sumValue) 00414 { 00415 State state; 00416 wxFileInputStream* in = getFileInputStream(fileName, state); 00417 if (in == NULL) 00418 return state; 00419 00420 state = ChecksumCalculator::calculate(*in, sumValue); 00421 delete in; 00422 return state; 00423 } 00424 //--------------------------------------------------------------------------- 00425 00426 00427 /** 00428 * Calculates the checksums from the given file. 00429 * 00430 * @param fileName Name of the file from which the data will be extracted to 00431 * compute the checksum. The data are extracted until the end 00432 * of the file is reached. 00433 * @param checksums Array of checksums to calculate. 00434 * @param sumValues The calculated values of the checksums from the input 00435 * stream. The array is erased first before adding results. 00436 * On success <CODE>ArrayChecksum.GetCount() == sumValues.GetCount()</CODE>, 00437 * on failure, <CODE>sumValues</CODE> should be empty. 00438 * @return <UL> 00439 * <LI><CODE>Ok</CODE> if the checksum has been successfully calculated.</Li> 00440 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00441 * <LI><CODE>FileNotFound</CODE> if the file doesn't exist.</LI> 00442 * <LI><CODE>CantOpenFile</CODE> if the file can't be opened.</LI> 00443 * <LI><CODE>Canceled</CODE> if the user has canceled the calculation.</LI> 00444 * </UL> 00445 */ 00446 ChecksumCalculator::State ChecksumFileCalculator::calculate(const wxString& fileName, 00447 const ArrayChecksum& checksums, 00448 wxArrayString& sumValues) 00449 { 00450 State state; 00451 wxFileInputStream* in = getFileInputStream(fileName, state); 00452 if (in == NULL) 00453 return state; 00454 00455 state = ChecksumCalculator::calculate(*in, checksums, sumValues); 00456 delete in; 00457 return state; 00458 } 00459 //--------------------------------------------------------------------------- 00460 00461 00462 /** 00463 * Checks the checksum from the given file. 00464 * 00465 * @param fileName Name of the file from which the data will be extracted to 00466 * compute the checksum. The data are extracted until the end 00467 * of the file is reached. 00468 * @param value The value of the checksum which will be compared with the 00469 * value that will be calculated. 00470 * @return <UL> 00471 * <LI><CODE>Ok</CODE> if the checksum has been successfully 00472 * calculated and if the two sums are equals.</LI> 00473 * <LI><CODE>Invalid</CODE> if the checksum has been successfully 00474 * calculated and if the two sums are not equals.</LI> 00475 * <LI><CODE>ReadError</CODE> if a read error has occured.</LI> 00476 * <LI><CODE>FileNotFound</CODE> if the file doesn't exist.</LI> 00477 * <LI><CODE>CantOpenFile</CODE> if the file can't be opened.</LI> 00478 * </UL> 00479 */ 00480 ChecksumFileCalculator::State ChecksumFileCalculator::check(const wxString& fileName, const wxString& value) 00481 { 00482 State state; 00483 wxFileInputStream* in = getFileInputStream(fileName, state); 00484 if (in == NULL) 00485 return state; 00486 00487 state = ChecksumCalculator::check(*in, value); 00488 delete in; 00489 return state; 00490 } 00491 //---------------------------------------------------------------------------