File indexing completed on 2024-04-28 04:49:52
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "k3bmd5job.h" 0007 #include "k3biso9660.h" 0008 #include "k3bglobals.h" 0009 #include "k3bdevice.h" 0010 #include "k3bfilesplitter.h" 0011 #include "k3b_i18n.h" 0012 0013 #include <QCryptographicHash> 0014 #include <QDebug> 0015 #include <QIODevice> 0016 #include <QTimer> 0017 0018 0019 class K3b::Md5Job::Private 0020 { 0021 public: 0022 Private() 0023 : md5(QCryptographicHash::Md5), 0024 ioDevice(0), 0025 finished(true), 0026 data(0), 0027 isoFile(0), 0028 maxSize(0), 0029 lastProgress(0) { 0030 } 0031 0032 QCryptographicHash md5; 0033 K3b::FileSplitter file; 0034 QTimer timer; 0035 QString filename; 0036 QIODevice* ioDevice; 0037 K3b::Device::Device* device; 0038 0039 bool finished; 0040 char* data; 0041 const K3b::Iso9660File* isoFile; 0042 0043 qint64 maxSize; 0044 qint64 readData; 0045 0046 int lastProgress; 0047 0048 KIO::filesize_t imageSize; 0049 0050 static const int BUFFERSIZE = 2048*10; 0051 }; 0052 0053 0054 K3b::Md5Job::Md5Job( K3b::JobHandler* jh, QObject* parent ) 0055 : K3b::Job( jh, parent ), 0056 d( new Private() ) 0057 { 0058 d->data = new char[Private::BUFFERSIZE]; 0059 connect( &d->timer, SIGNAL(timeout()), 0060 this, SLOT(slotUpdate()) ); 0061 } 0062 0063 0064 K3b::Md5Job::~Md5Job() 0065 { 0066 delete [] d->data; 0067 delete d; 0068 } 0069 0070 0071 void K3b::Md5Job::start() 0072 { 0073 cancel(); 0074 0075 jobStarted(); 0076 d->readData = 0; 0077 0078 if( d->isoFile ) { 0079 d->imageSize = d->isoFile->size(); 0080 } 0081 else if( !d->filename.isEmpty() ) { 0082 if( !QFile::exists( d->filename ) ) { 0083 emit infoMessage( i18n("Could not find file %1",d->filename), MessageError ); 0084 jobFinished(false); 0085 return; 0086 } 0087 0088 d->file.setName( d->filename ); 0089 if( !d->file.open( QIODevice::ReadOnly ) ) { 0090 emit infoMessage( i18n("Could not open file %1",d->filename), MessageError ); 0091 jobFinished(false); 0092 return; 0093 } 0094 0095 d->imageSize = K3b::filesize( QUrl::fromLocalFile(d->filename) ); 0096 } 0097 else 0098 d->imageSize = 0; 0099 0100 if( d->device ) { 0101 // 0102 // Let the drive determine the optimal reading speed 0103 // 0104 d->device->setSpeed( 0xffff, 0xffff ); 0105 } 0106 0107 d->md5.reset(); 0108 d->finished = false; 0109 if( d->ioDevice ) 0110 connect( d->ioDevice, SIGNAL(readyRead()), this, SLOT(slotUpdate()) ); 0111 else 0112 d->timer.start(0); 0113 } 0114 0115 0116 void K3b::Md5Job::cancel() 0117 { 0118 if( !d->finished ) { 0119 stopAll(); 0120 0121 emit canceled(); 0122 jobFinished( false ); 0123 } 0124 } 0125 0126 0127 void K3b::Md5Job::setFile( const QString& filename ) 0128 { 0129 d->filename = filename; 0130 d->isoFile = 0; 0131 d->ioDevice = 0; 0132 d->device = 0; 0133 } 0134 0135 0136 void K3b::Md5Job::setFile( const K3b::Iso9660File* file ) 0137 { 0138 d->isoFile = file; 0139 d->ioDevice = 0; 0140 d->filename.truncate(0); 0141 d->device = 0; 0142 } 0143 0144 0145 void K3b::Md5Job::setIODevice( QIODevice* dev ) 0146 { 0147 d->ioDevice = dev; 0148 d->filename.truncate(0); 0149 d->isoFile = 0; 0150 d->device = 0; 0151 } 0152 0153 0154 void K3b::Md5Job::setDevice( K3b::Device::Device* dev ) 0155 { 0156 d->device = dev; 0157 d->ioDevice = 0; 0158 d->filename.truncate(0); 0159 d->isoFile = 0; 0160 } 0161 0162 0163 void K3b::Md5Job::setMaxReadSize( qint64 size ) 0164 { 0165 d->maxSize = size; 0166 } 0167 0168 0169 void K3b::Md5Job::slotUpdate() 0170 { 0171 if( !d->finished ) { 0172 0173 // determine bytes to read 0174 qint64 readSize = Private::BUFFERSIZE; 0175 if( d->maxSize > 0 ) 0176 readSize = qMin( readSize, d->maxSize - d->readData ); 0177 0178 if( readSize <= 0 ) { 0179 // qDebug() << "(K3b::Md5Job) reached max size of " << d->maxSize << ". Stopping."; 0180 emit debuggingOutput( "K3b::Md5Job", QString("Reached max read of %1. Stopping after %2 bytes.").arg(d->maxSize).arg(d->readData) ); 0181 stopAll(); 0182 emit percent( 100 ); 0183 jobFinished(true); 0184 } 0185 else { 0186 int read = 0; 0187 0188 // 0189 // read from the iso9660 file 0190 // 0191 if( d->isoFile ) { 0192 read = d->isoFile->read( d->readData, d->data, readSize ); 0193 } 0194 0195 // 0196 // read from the device 0197 // 0198 else if( d->device ) { 0199 // 0200 // when reading from a device we always read multiples of 2048 bytes. 0201 // Only the last sector may not be used completely. 0202 // 0203 qint64 sector = d->readData/2048; 0204 qint64 sectorCnt = qMax( readSize/2048, ( qint64 )1 ); 0205 read = -1; 0206 if( d->device->read10( reinterpret_cast<unsigned char*>(d->data), 0207 sectorCnt*2048, 0208 sector, 0209 sectorCnt ) ) 0210 read = qMin( readSize, sectorCnt*2048 ); 0211 } 0212 0213 // 0214 // read from the file 0215 // 0216 else if( !d->ioDevice ) { 0217 read = d->file.read( d->data, readSize ); 0218 } 0219 0220 // 0221 // reading from the io device 0222 // 0223 else { 0224 read = d->ioDevice->read( d->data, readSize ); 0225 } 0226 0227 if( read < 0 ) { 0228 emit infoMessage( i18n("Error while reading from file %1", d->filename), MessageError ); 0229 stopAll(); 0230 jobFinished(false); 0231 } 0232 else if( read == 0 ) { 0233 // qDebug() << "(K3b::Md5Job) read all data. Total size: " << d->readData << ". Stopping."; 0234 emit debuggingOutput( "K3b::Md5Job", QString("All data read. Stopping after %1 bytes.").arg(d->readData) ); 0235 stopAll(); 0236 emit percent( 100 ); 0237 jobFinished(true); 0238 } 0239 else { 0240 d->readData += read; 0241 d->md5.addData( d->data, read ); 0242 int progress = 0; 0243 if( d->isoFile || !d->filename.isEmpty() ) 0244 progress = (int)((double)d->readData * 100.0 / (double)d->imageSize); 0245 else if( d->maxSize > 0 ) 0246 progress = (int)((double)d->readData * 100.0 / (double)d->maxSize); 0247 0248 if( progress != d->lastProgress ) { 0249 d->lastProgress = progress; 0250 emit percent( progress ); 0251 } 0252 } 0253 } 0254 } 0255 } 0256 0257 0258 QByteArray K3b::Md5Job::hexDigest() 0259 { 0260 if( d->finished ) 0261 return d->md5.result().toHex(); 0262 else 0263 return ""; 0264 } 0265 0266 0267 QByteArray K3b::Md5Job::base64Digest() 0268 { 0269 if( d->finished ) 0270 return d->md5.result().toBase64(); 0271 else 0272 return ""; 0273 } 0274 0275 0276 void K3b::Md5Job::stop() 0277 { 0278 emit debuggingOutput( "K3b::Md5Job", QString("Stopped manually after %1 bytes.").arg(d->readData) ); 0279 stopAll(); 0280 jobFinished( true ); 0281 } 0282 0283 0284 void K3b::Md5Job::stopAll() 0285 { 0286 if( d->ioDevice ) 0287 disconnect( d->ioDevice, SIGNAL(readyRead()), this, SLOT(slotUpdate()) ); 0288 if( d->file.isOpen() ) 0289 d->file.close(); 0290 d->timer.stop(); 0291 d->finished = true; 0292 } 0293 0294 #include "moc_k3bmd5job.cpp"