File indexing completed on 2025-01-05 04:37:29
0001 /* 0002 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "extractfilejob.h" 0008 #include <KIO/Global> 0009 #include <QFile> 0010 #include <QThread> 0011 0012 namespace bt 0013 { 0014 class ExtractFileThread : public QThread 0015 { 0016 public: 0017 ExtractFileThread(QIODevice *in_dev, QIODevice *out_dev) 0018 : in_dev(in_dev) 0019 , out_dev(out_dev) 0020 , canceled(false) 0021 { 0022 } 0023 0024 ~ExtractFileThread() override 0025 { 0026 delete in_dev; 0027 delete out_dev; 0028 } 0029 0030 void run() override 0031 { 0032 char buf[4096]; 0033 qint64 ret = 0; 0034 while ((ret = in_dev->read(buf, 4096)) != 0 && !canceled) { 0035 out_dev->write(buf, ret); 0036 } 0037 } 0038 0039 QIODevice *in_dev; 0040 QIODevice *out_dev; 0041 bool canceled; 0042 }; 0043 0044 ExtractFileJob::ExtractFileJob(KArchive *archive, const QString &path, const QString &dest) 0045 : archive(archive) 0046 , path(path) 0047 , dest(dest) 0048 , extract_thread(nullptr) 0049 { 0050 } 0051 0052 ExtractFileJob::~ExtractFileJob() 0053 { 0054 delete archive; 0055 } 0056 0057 void ExtractFileJob::start() 0058 { 0059 // first find the file in the archive 0060 QStringList path_components = path.split(QLatin1Char('/'), Qt::SkipEmptyParts); 0061 const KArchiveDirectory *dir = archive->directory(); 0062 for (int i = 0; i < path_components.count(); i++) { 0063 // if we can't find it give back an error 0064 QString pc = path_components.at(i); 0065 if (!dir->entries().contains(pc)) { 0066 setError(KIO::ERR_DOES_NOT_EXIST); 0067 emitResult(); 0068 return; 0069 } 0070 0071 const KArchiveEntry *e = dir->entry(pc); 0072 if (i < path_components.count() - 1) { 0073 // if we are not the last entry in the path, e must be a directory 0074 if (!e->isDirectory()) { 0075 setError(KIO::ERR_DOES_NOT_EXIST); 0076 emitResult(); 0077 return; 0078 } 0079 0080 dir = (const KArchiveDirectory *)e; 0081 } else { 0082 // last in the path, must be a file 0083 if (!e->isFile()) { 0084 setError(KIO::ERR_DOES_NOT_EXIST); 0085 emitResult(); 0086 return; 0087 } 0088 0089 // create a device to read the file and start a thread to do the reading 0090 KArchiveFile *file = (KArchiveFile *)e; 0091 QFile *out_dev = new QFile(dest); 0092 if (!out_dev->open(QIODevice::WriteOnly)) { 0093 delete out_dev; 0094 setError(KIO::ERR_CANNOT_OPEN_FOR_WRITING); 0095 emitResult(); 0096 return; 0097 } 0098 0099 QIODevice *in_dev = file->createDevice(); 0100 extract_thread = new ExtractFileThread(in_dev, out_dev); 0101 connect(extract_thread, &ExtractFileThread::finished, this, &ExtractFileJob::extractThreadDone, Qt::QueuedConnection); 0102 extract_thread->start(); 0103 } 0104 } 0105 } 0106 0107 void ExtractFileJob::kill(bool quietly) 0108 { 0109 if (extract_thread) { 0110 extract_thread->canceled = true; 0111 extract_thread->wait(); 0112 delete extract_thread; 0113 extract_thread = nullptr; 0114 } 0115 setError(KIO::ERR_USER_CANCELED); 0116 if (!quietly) 0117 emitResult(); 0118 } 0119 0120 void ExtractFileJob::extractThreadDone() 0121 { 0122 extract_thread->wait(); 0123 delete extract_thread; 0124 extract_thread = nullptr; 0125 setError(0); 0126 emitResult(); 0127 } 0128 0129 }