Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

md5file.cpp

Go to the documentation of this file.
00001 /* 00002 * wxChecksums 00003 * Copyright (C) 2003-2004 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 md5file.cpp 00022 * Classes that encapsulate %MD5 files. 00023 */ 00024 00025 //--------------------------------------------------------------------------- 00026 // For compilers that support precompilation, includes "wx.h". 00027 #include <wx/wxprec.h> 00028 00029 #ifdef __BORLANDC__ 00030 #pragma hdrstop 00031 #endif 00032 00033 #ifndef WX_PRECOMP 00034 // Include your minimal set of headers here, or wx.h 00035 #include <wx/wx.h> 00036 #endif 00037 00038 #include <wx/txtstrm.h> 00039 #include <wx/wfstream.h> 00040 00041 #include "md5file.hpp" 00042 #include "appprefs.hpp" 00043 #include "md5.hpp" 00044 #include "osdep.hpp" 00045 #include "utils.hpp" 00046 00047 #include "compat.hpp" 00048 //--------------------------------------------------------------------------- 00049 00050 /// The C++ standard namespace. 00051 using namespace std; 00052 00053 00054 /** 00055 * Default constructor. 00056 */ 00057 MD5File::MD5File() : SumFile() 00058 { 00059 } 00060 //--------------------------------------------------------------------------- 00061 00062 00063 /** 00064 * Clones the source instance in this instance. 00065 * 00066 * Don't forget to call this method when cloning inherited classes. 00067 * 00068 * @param source Source instance. 00069 */ 00070 void MD5File::clone(const MD5File& source) 00071 { 00072 SumFile::clone(source); 00073 } 00074 //--------------------------------------------------------------------------- 00075 00076 00077 /** 00078 * Copy constructor. 00079 * 00080 * @param source Source instance. 00081 */ 00082 MD5File::MD5File(const MD5File& source) 00083 { 00084 clone(source); 00085 } 00086 //--------------------------------------------------------------------------- 00087 00088 00089 /** 00090 * Assignment operator. 00091 * 00092 * @param source Source instance. 00093 * @return A reference on the instance. 00094 */ 00095 MD5File& MD5File::operator=(const MD5File& source) 00096 { 00097 clone(source); 00098 return *this; 00099 } 00100 //--------------------------------------------------------------------------- 00101 00102 00103 /** 00104 * Returns an instance of a class that permits to compute the MD5 value. 00105 * 00106 * The calling function is responsible of the deletion of the instance with 00107 * the <CODE>delete</CODE> operator. 00108 * 00109 * @return An instance of a class that permits to compute the checksum value. 00110 */ 00111 Checksum* MD5File::getChecksumCalculator() const 00112 { 00113 return new MD5(); 00114 } 00115 //--------------------------------------------------------------------------- 00116 00117 00118 /** 00119 * Returns the type of the file. 00120 * 00121 * @return The type of the file. 00122 */ 00123 wxString MD5File::getFileType() const 00124 { 00125 return wxString(wxT("MD5")); 00126 } 00127 //--------------------------------------------------------------------------- 00128 00129 00130 /** 00131 * Reads the checksums from a MD5 file. 00132 * 00133 * After the reading of the file, the state of the file should be unmodified 00134 * and on success, the checksum file name must be the given one (absolute 00135 * path). 00136 * 00137 * The paths of the files in the ChecksumData must be relative to the path of 00138 * <CODE>fileName</CODE>. 00139 * 00140 * The information about the type of the file (text or binary) is skipped, 00141 * wxChecksums always reads files in binary mode. 00142 * 00143 * @param fileName The file name from which the checksums are read. 00144 * @return <CODE>true</CODE> if the file has been read successfully, 00145 * <CODE>false</CODE> otherwise. 00146 */ 00147 bool MD5File::read(const wxFileName& fileName) 00148 { 00149 const int MAX_INVALID = 64; 00150 wxString line; // line of text 00151 size_t l; // size of the line 00152 size_t i; // counter 00153 bool comment; // line is a comment 00154 bool stop; // stop searching for comment 00155 int invalid = 0; // counter of invalid lines 00156 int valid = 0; // counter of valid lines 00157 int ccomment = 0; // counter of comments lines 00158 wxChar c; // a character 00159 wxString name; // name of the file 00160 wxString sum; // value of the checksum 00161 wxFileName nameRel; // File name with a relative path 00162 wxFileName nameAbs; // File name with ab absolute path 00163 wxPathFormat format; // Format of the path separators in the file 00164 00165 // No log 00166 wxLogNull logNo; 00167 00168 // Gets the path separator 00169 format = static_cast<wxPathFormat>(AppPrefs::get()->readLong(prMD5_READ_PATH_SEPARATOR)); 00170 if (format == wxPATH_NATIVE) 00171 format = getPathFormat(fileName); 00172 00173 // Opens the file 00174 wxFileInputStream input(fileName.GetFullPath()); 00175 if (!input.Ok()) 00176 return false; 00177 wxTextInputStream text(input); 00178 00179 // Resets the file. 00180 reset(); 00181 00182 // Reads the lines 00183 line = text.ReadLine(); 00184 while (!input.Eof() && invalid - valid <= MAX_INVALID) 00185 { 00186 l = line.size(); 00187 00188 // Checks if the line is a comment or is empty 00189 i = 0; 00190 stop = false; 00191 comment = line.empty(); 00192 while (!stop && !comment && i < l) 00193 { 00194 c = line[i]; 00195 if (c == wxT(';')) 00196 comment = true; 00197 else 00198 if (line[i] == wxT(' ') || line[i] == wxT('\t')) 00199 i++; 00200 else 00201 stop = true; 00202 } 00203 00204 if (comment || i == l) 00205 // Ignore the line, but the line is valid 00206 { 00207 valid++; 00208 ccomment++; 00209 } 00210 else // Reads the file name and the checksum 00211 { 00212 if (line.size() > 34) // size of sum + separator char + binary flag char 00213 { 00214 sum = line.Left(32); 00215 name = line.Right(line.size() - 34); 00216 if (!IsValidChecksum(sum) || name.empty()) 00217 // Line is not valid 00218 invalid++; 00219 else 00220 { 00221 valid++; 00222 00223 nameAbs.Assign(name, format); 00224 if (!nameAbs.IsAbsolute()) 00225 nameAbs.MakeAbsolute(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00226 nameRel = nameAbs; 00227 if (!nameRel.IsRelative()) 00228 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00229 00230 addChecksumData(ChecksumData(nameRel, sum, ChecksumData::NotVerified)); 00231 } 00232 } 00233 else // Line is not valid 00234 invalid++; 00235 } 00236 00237 line = text.ReadLine(); 00238 } 00239 00240 valid -= ccomment; 00241 if ((invalid - valid <= MAX_INVALID && valid > 0) || 00242 (valid == 0 && invalid == 0)) 00243 { 00244 setFileName(fileName.GetFullPath()); 00245 setModified(false); 00246 return true; 00247 } 00248 00249 return false; 00250 } 00251 //--------------------------------------------------------------------------- 00252 00253 00254 /** 00255 * Writes the checksums in a file. 00256 * 00257 * After the writing of the file, the state of the file should be unmodified 00258 * and the file name must be modified to <CODE>fileName</CODE>. 00259 * The paths of the files in the ChecksumData must be relative to the path of 00260 * <CODE>fileName</CODE>. 00261 * 00262 * As wxChecksums always reads files in binary mode, all the file are marked 00263 * as binary files. 00264 * 00265 * @param fileName The file name in which the checksums are written. 00266 * @return <CODE>true</CODE> if the checksums have been written successfully, 00267 * <CODE>false</CODE> otherwise. 00268 */ 00269 bool MD5File::write(const wxFileName& fileName) 00270 { 00271 wxLogNull logNo; // No log 00272 wxString line; // line of text 00273 wxDateTime d; // A date 00274 wxFileName nameRel; // File name with a relative path 00275 wxFileName nameAbs; // File name with ab absolute path 00276 wxCOff_t length; // Length of the file 00277 wxPathFormat format; // Format of the path separators in the file 00278 00279 wxFileOutputStream output(fileName.GetFullPath()); 00280 if (!output.Ok()) 00281 return false; 00282 wxTextOutputStream text(output, static_cast<wxEOL>(AppPrefs::get()->readLong(prMD5_WRITE_EOL))); 00283 00284 // Gets the path separator 00285 format = static_cast<wxPathFormat>(AppPrefs::get()->readLong(prMD5_WRITE_PATH_SEPARATOR)); 00286 00287 // Write header 00288 if (AppPrefs::get()->readBool(prMD5_WRITE_GEN_AND_DATE)) 00289 { 00290 d = wxDateTime::Now(); 00291 line.Printf(wxT("; Generated by %s on %s at %s\n"), ::getAppName().c_str(), 00292 d.Format(wxT("%Y-%m-%d")).c_str(), d.Format(wxT("%H:%M:%S")).c_str()); 00293 text.WriteString(line); 00294 text.WriteString(wxT(";\n")); 00295 } 00296 00297 // Write the size and the date of the files 00298 if (AppPrefs::get()->readBool(prMD5_WRITE_FILE_SIZE_AND_DATE)) 00299 { 00300 MChecksumData::const_iterator it = getChecksumDataBegin(); 00301 MChecksumData::const_iterator end = getChecksumDataEnd(); 00302 00303 while (it != end) 00304 { 00305 const ChecksumData& cd = it->second; 00306 nameAbs = cd.getFileName(); 00307 if (!nameAbs.IsAbsolute()) 00308 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00309 nameRel = nameAbs; 00310 if (!nameRel.IsRelative()) 00311 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00312 00313 if ((length = wxCGetFileLength(nameAbs.GetFullPath())) != static_cast<wxCOff_t>(wxInvalidOffset)) 00314 { 00315 #if defined(wxC_USE_LARGE_FILES) 00316 text.WriteString(wxString::Format(wxT("; %12" wxLongLongFmtSpec "u "), length)); 00317 #else 00318 text.WriteString(wxString::Format(wxT("; %12u "), length)); 00319 #endif 00320 d = nameAbs.GetModificationTime(); 00321 text << d.Format(wxT("%H:%M.%S")) << wxT(" ") << d.Format(wxT("%Y-%m-%d")); 00322 text << wxT(" ") << nameRel.GetFullPath(format) << wxT("\n"); 00323 } 00324 it++; 00325 } 00326 } 00327 00328 // Write checksums 00329 MChecksumData::const_iterator it = getChecksumDataBegin(); 00330 MChecksumData::const_iterator end = getChecksumDataEnd(); 00331 00332 while (it != end) 00333 { 00334 const ChecksumData& cd = it->second; 00335 nameAbs = cd.getFileName(); 00336 if (!nameAbs.IsAbsolute()) 00337 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00338 nameRel = nameAbs; 00339 if (!nameRel.IsRelative()) 00340 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00341 00342 text << cd.getChecksum().Lower() << wxT(" *") 00343 << nameRel.GetFullPath(format) << wxT("\n"); 00344 it++; 00345 } 00346 00347 if (output.IsOk()) 00348 { 00349 // Modify file paths if the path of the checksum file has been modified. 00350 { 00351 MChecksumData::iterator it = getChecksumDataBeginI(); 00352 MChecksumData::iterator end = getChecksumDataEndI(); 00353 00354 while (it != end) 00355 { 00356 ChecksumData& cd = it->second; 00357 nameAbs = cd.getFileName(); 00358 if (!nameAbs.IsAbsolute()) 00359 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00360 nameRel = nameAbs; 00361 if (!nameRel.IsRelative()) 00362 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00363 00364 cd.setFileName(nameRel); 00365 it++; 00366 } 00367 } 00368 00369 this->setFileName(fileName.GetFullPath()); 00370 this->setModified(false); 00371 return true; 00372 } 00373 else 00374 return false; 00375 } 00376 //--------------------------------------------------------------------------- 00377 00378 00379 /** 00380 * Indicates if the given checksum is valid. 00381 * 00382 * @param checksum The checksum to check. 00383 */ 00384 bool MD5File::IsValidChecksum(const wxString& checksum) 00385 { 00386 const wxString validCaracters = wxT("0123456789abcdefABCDEF"); 00387 wxChar c; 00388 size_t i, j; 00389 size_t l = checksum.size(); 00390 size_t s = validCaracters.size(); 00391 bool OK, found; 00392 00393 i = 0; 00394 OK = (checksum.size() == 32); 00395 while (OK && i < l) 00396 { 00397 c = checksum[i]; 00398 j = 0; 00399 found = false; 00400 while (!found && j < s) 00401 { 00402 if (c == validCaracters[j]) 00403 found = true; 00404 j++; 00405 } 00406 00407 if (!found) 00408 OK = false; 00409 i++; 00410 } 00411 00412 return OK; 00413 } 00414 //--------------------------------------------------------------------------- 00415 00416 00417 /** 00418 * Gets a new instance of this class. 00419 * 00420 * The caller is responsible of the deletion of the instance with the 00421 * <CODE>delete</CODE> operator. 00422 * 00423 * @return A new instance of this class. 00424 */ 00425 SumFile* MD5File::getNewInstance() 00426 { 00427 return new MD5File(); 00428 } 00429 //---------------------------------------------------------------------------

Generated on Sun May 30 13:37:45 2004 for wxChecksums by doxygen 1.3.7