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

sfvfile.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 sfvfile.cpp 00022 * Classes that encapsulate SFV 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 "sfvfile.hpp" 00042 #include "appprefs.hpp" 00043 #include "crc32.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 SFVFile::SFVFile() : 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 SFVFile::clone(const SFVFile& source) 00071 { 00072 SumFile::clone(source); 00073 } 00074 //--------------------------------------------------------------------------- 00075 00076 00077 /** 00078 * Copy constructor. 00079 * 00080 * @param source Source instance. 00081 */ 00082 SFVFile::SFVFile(const SFVFile& 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 SFVFile& SFVFile::operator=(const SFVFile& 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 CRC-32 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* SFVFile::getChecksumCalculator() const 00112 { 00113 return new CRC32(); 00114 } 00115 //--------------------------------------------------------------------------- 00116 00117 00118 /** 00119 * Returns the type of the file. 00120 * 00121 * @return The type of the file. 00122 */ 00123 wxString SFVFile::getFileType() const 00124 { 00125 return wxString(wxT("SFV")); 00126 } 00127 //--------------------------------------------------------------------------- 00128 00129 00130 /** 00131 * Reads the checksums from a SFV 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 * @param fileName The file name from which the checksums are read. 00141 * @return <CODE>true</CODE> if the file has been read successfully, 00142 * <CODE>false</CODE> otherwise. 00143 */ 00144 bool SFVFile::read(const wxFileName& fileName) 00145 { 00146 const int MAX_INVALID = 64; 00147 wxString line; // line of text 00148 size_t l; // size of the line 00149 size_t i; // counter 00150 bool comment; // line is a comment 00151 bool stop; // stop searching for comment 00152 int invalid = 0; // counter of invalid lines 00153 int valid = 0; // counter of valid lines 00154 int ccomment = 0; // counter of comments lines 00155 wxChar c; // a character 00156 wxString name; // name of the file 00157 wxString sum; // value of the checksum 00158 wxFileName nameRel; // File name with a relative path 00159 wxFileName nameAbs; // File name with ab absolute path 00160 wxPathFormat format; // Format of the path separators in the file 00161 00162 // No log 00163 wxLogNull logNo; 00164 00165 // Gets the path separator 00166 format = static_cast<wxPathFormat>(AppPrefs::get()->readLong(prSFV_READ_PATH_SEPARATOR)); 00167 if (format == wxPATH_NATIVE) 00168 format = getPathFormat(fileName); 00169 00170 // Opens the file 00171 wxFileInputStream input(fileName.GetFullPath()); 00172 if (!input.Ok()) 00173 return false; 00174 wxTextInputStream text(input); 00175 00176 // Resets the file. 00177 reset(); 00178 00179 // Reads the lines 00180 line = text.ReadLine(); 00181 while (!input.Eof() && invalid - valid <= MAX_INVALID) 00182 { 00183 l = line.size(); 00184 00185 // Checks if the line is a comment or is empty 00186 i = 0; 00187 stop = false; 00188 comment = line.empty(); 00189 while (!stop && !comment && i < l) 00190 { 00191 c = line[i]; 00192 if (c == wxT(';')) 00193 comment = true; 00194 else 00195 if (line[i] == wxT(' ') || line[i] == wxT('\t')) 00196 i++; 00197 else 00198 stop = true; 00199 } 00200 00201 if (comment || i == l) 00202 // Ignore the line, but the line is valid 00203 { 00204 valid++; 00205 ccomment++; 00206 } 00207 else // Reads the file name and the checksum 00208 { 00209 name = line.BeforeLast(wxT(' ')); 00210 sum = line.AfterLast(wxT(' ')); 00211 if (name.empty() || !IsValidChecksum(sum)) 00212 // Try with tab 00213 { 00214 name = line.BeforeLast(wxT('\t')); 00215 sum = line.AfterLast(wxT('\t')); 00216 } 00217 if (name.empty() || !IsValidChecksum(sum)) 00218 // Line is not valid 00219 invalid++; 00220 else 00221 { 00222 valid++; 00223 00224 nameAbs.Assign(name, format); 00225 if (!nameAbs.IsAbsolute()) 00226 nameAbs.MakeAbsolute(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00227 nameRel = nameAbs; 00228 if (!nameRel.IsRelative()) 00229 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00230 00231 addChecksumData(ChecksumData(nameRel, sum, ChecksumData::NotVerified)); 00232 } 00233 } 00234 00235 line = text.ReadLine(); 00236 } 00237 00238 valid -= ccomment; 00239 if ((invalid - valid <= MAX_INVALID && valid > 0) || 00240 (valid == 0 && invalid == 0)) 00241 { 00242 setFileName(fileName.GetFullPath()); 00243 setModified(false); 00244 return true; 00245 } 00246 00247 return false; 00248 } 00249 //--------------------------------------------------------------------------- 00250 00251 00252 /** 00253 * Writes the checksums in a file. 00254 * 00255 * After the writing of the file, the state of the file should be unmodified 00256 * and the file name must be modified to <CODE>fileName</CODE>. 00257 * The paths of the files in the ChecksumData must be relative to the path of 00258 * <CODE>fileName</CODE>. 00259 * 00260 * @param fileName The file name in which the checksums are written. 00261 * @return <CODE>true</CODE> if the checksums have been written successfully, 00262 * <CODE>false</CODE> otherwise. 00263 */ 00264 bool SFVFile::write(const wxFileName& fileName) 00265 { 00266 wxLogNull logNo; // No log 00267 wxString line; // line of text 00268 wxDateTime d; // A date 00269 wxFileName nameRel; // File name with a relative path 00270 wxFileName nameAbs; // File name with ab absolute path 00271 wxCOff_t length; // Length of the file 00272 wxPathFormat format; // Format of the path separators in the file 00273 00274 wxFileOutputStream output(fileName.GetFullPath()); 00275 if (!output.Ok()) 00276 return false; 00277 wxTextOutputStream text(output, static_cast<wxEOL>(AppPrefs::get()->readLong(prSFV_WRITE_EOL))); 00278 00279 // Gets the path separator 00280 format = static_cast<wxPathFormat>(AppPrefs::get()->readLong(prSFV_WRITE_PATH_SEPARATOR)); 00281 00282 // Write header 00283 if (AppPrefs::get()->readBool(prSFV_WRITE_GEN_AND_DATE)) 00284 { 00285 d = wxDateTime::Now(); 00286 wxString generator = AppPrefs::get()->readString(prSFV_IDENTIFY_AS); 00287 if (generator.IsEmpty()) 00288 generator = ::getAppName(); 00289 line.Printf(wxT("; Generated by %s on %s at %s\n"), generator.c_str(), 00290 d.Format(wxT("%Y-%m-%d")).c_str(), d.Format(wxT("%H:%M:%S")).c_str()); 00291 text.WriteString(line); 00292 text.WriteString(wxT(";\n")); 00293 } 00294 00295 // Write the size and the date of the files 00296 if (AppPrefs::get()->readBool(prSFV_WRITE_FILE_SIZE_AND_DATE)) 00297 { 00298 MChecksumData::const_iterator it = getChecksumDataBegin(); 00299 MChecksumData::const_iterator end = getChecksumDataEnd(); 00300 00301 while (it != end) 00302 { 00303 const ChecksumData& cd = it->second; 00304 nameAbs = cd.getFileName(); 00305 if (!nameAbs.IsAbsolute()) 00306 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00307 nameRel = nameAbs; 00308 if (!nameRel.IsRelative()) 00309 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00310 00311 if ((length = wxCGetFileLength(nameAbs.GetFullPath())) != static_cast<wxCOff_t>(wxInvalidOffset)) 00312 { 00313 #if defined(wxC_USE_LARGE_FILES) 00314 text.WriteString(wxString::Format(wxT("; %12" wxLongLongFmtSpec "u "), length)); 00315 #else 00316 text.WriteString(wxString::Format(wxT("; %12u "), length)); 00317 #endif 00318 d = nameAbs.GetModificationTime(); 00319 text << d.Format(wxT("%H:%M.%S")) << wxT(" ") << d.Format(wxT("%Y-%m-%d")); 00320 text << wxT(" ") << nameRel.GetFullPath(format) << wxT("\n"); 00321 } 00322 it++; 00323 } 00324 } 00325 00326 // Write checksums 00327 MChecksumData::const_iterator it = getChecksumDataBegin(); 00328 MChecksumData::const_iterator end = getChecksumDataEnd(); 00329 00330 while (it != end) 00331 { 00332 const ChecksumData& cd = it->second; 00333 nameAbs = cd.getFileName(); 00334 if (!nameAbs.IsAbsolute()) 00335 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00336 nameRel = nameAbs; 00337 if (!nameRel.IsRelative()) 00338 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00339 00340 text << nameRel.GetFullPath(format) << wxT(" ") 00341 << cd.getChecksum().Upper() << wxT("\n"); 00342 it++; 00343 } 00344 00345 if (output.IsOk()) 00346 { 00347 // Modify file paths if the path of the checksum file has been modified. 00348 { 00349 MChecksumData::iterator it = getChecksumDataBeginI(); 00350 MChecksumData::iterator end = getChecksumDataEndI(); 00351 00352 while (it != end) 00353 { 00354 ChecksumData& cd = it->second; 00355 nameAbs = cd.getFileName(); 00356 if (!nameAbs.IsAbsolute()) 00357 nameAbs.MakeAbsolute(wxFileName(this->getFileName()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00358 nameRel = nameAbs; 00359 if (!nameRel.IsRelative()) 00360 nameRel.MakeRelativeTo(fileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); 00361 00362 cd.setFileName(nameRel); 00363 it++; 00364 } 00365 } 00366 00367 this->setFileName(fileName.GetFullPath()); 00368 this->setModified(false); 00369 return true; 00370 } 00371 else 00372 return false; 00373 } 00374 //--------------------------------------------------------------------------- 00375 00376 00377 /** 00378 * Indicates if the given checksum is valid. 00379 * 00380 * @param checksum The checksum to check. 00381 */ 00382 bool SFVFile::IsValidChecksum(const wxString& checksum) 00383 { 00384 const wxString validCaracters = wxT("0123456789abcdefABCDEF"); 00385 wxChar c; 00386 size_t i, j; 00387 size_t l = checksum.size(); 00388 size_t s = validCaracters.size(); 00389 bool OK, found; 00390 00391 i = 0; 00392 OK = (checksum.size() == 8); 00393 while (OK && i < l) 00394 { 00395 c = checksum[i]; 00396 j = 0; 00397 found = false; 00398 while (!found && j < s) 00399 { 00400 if (c == validCaracters[j]) 00401 found = true; 00402 j++; 00403 } 00404 00405 if (!found) 00406 OK = false; 00407 i++; 00408 } 00409 00410 return OK; 00411 } 00412 //--------------------------------------------------------------------------- 00413 00414 00415 /** 00416 * Gets a new instance of this class. 00417 * 00418 * The caller is responsible of the deletion of the instance with the 00419 * <CODE>delete</CODE> operator. 00420 * 00421 * @return A new instance of this class. 00422 */ 00423 SumFile* SFVFile::getNewInstance() 00424 { 00425 return new SFVFile(); 00426 } 00427 //---------------------------------------------------------------------------

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