File indexing completed on 2024-05-12 04:46:01

0001 #include "compressedfile.h"
0002 
0003 #include <KArchive/KTar>
0004 #include <KArchive/KZip>
0005 #include <KArchive/kcompressiondevice.h>
0006 #include <KArchive/kfilterdev.h>
0007 
0008 #if (defined Q_OS_LINUX || defined Q_OS_FREEBSD) && !defined Q_OS_ANDROID
0009 #include <KArchive/k7zip.h>
0010 #endif
0011 
0012 #include <KArchive/kar.h>
0013 
0014 #include <QDirIterator>
0015 #include <QDebug>
0016 
0017 #include <MauiKit3/FileBrowsing/fmstatic.h>
0018 
0019 
0020 CompressedFile::CompressedFile(QObject *parent)
0021   : QObject(parent)
0022   , m_model(new CompressedFileModel(this))
0023 {
0024 }
0025 
0026 CompressedFileModel::CompressedFileModel(QObject *parent)
0027   : MauiList(parent)
0028 {
0029 }
0030 
0031 const FMH::MODEL_LIST &CompressedFileModel::items() const
0032 {
0033   return m_list;
0034 }
0035 
0036 void CompressedFileModel::setUrl(const QUrl &url)
0037 {
0038   if(m_url == url)
0039     {
0040       return;
0041     }
0042 
0043   qDebug() << "@gadominguez File:fm.cpp Funcion: getEntries  Url:" << url.toString();
0044 
0045   KArchive *kArch = CompressedFile::getKArchiveObject(url);
0046   kArch->open(QIODevice::ReadOnly);
0047   assert(kArch->isOpen() == true);
0048   if (kArch->isOpen())
0049     {
0050       Q_EMIT this->preListChanged();
0051       m_list.clear();
0052 
0053       qDebug() << "@gadominguez File:fm.cpp Funcion: getEntries  Entries:" << kArch->directory()->entries();
0054 
0055       const auto entries = kArch->directory()->entries();
0056       for (const auto &entry : entries)
0057         {
0058           const auto e = kArch->directory()->entry(entry);
0059           this->m_list << FMH::MODEL{{FMH::MODEL_KEY::LABEL, e->name()}, {FMH::MODEL_KEY::ICON, e->isDirectory() ? "folder" : FMStatic::getIconName(e->name())}, {FMH::MODEL_KEY::DATE, e->date().toString()}};
0060 
0061         }
0062 
0063       Q_EMIT this->postListChanged();
0064       Q_EMIT this->countChanged ();
0065     }
0066 }
0067 
0068 void CompressedFile::extract(const QUrl &where, const QString &directory)
0069 {
0070   if (!m_url.isLocalFile())
0071     return;
0072 
0073   qDebug() << "@gadominguez File:fm.cpp Funcion: extractFile  "
0074              << "URL: " << m_url << "WHERE: " << where.toString() << " DIR: " << directory;
0075 
0076   QString where_ = where.toLocalFile() + "/" + directory;
0077 
0078   auto kArch = CompressedFile::getKArchiveObject(m_url);
0079   kArch->open(QIODevice::ReadOnly);
0080   qDebug() << "@gadominguez File:fm.cpp Funcion: extractFile  " << kArch->directory()->entries();
0081   assert(kArch->isOpen() == true);
0082 
0083   if (kArch->isOpen())
0084     {
0085       if(kArch->directory()->copyTo(where_, true))
0086         {
0087           Q_EMIT this->extractionFinished (where);
0088         }
0089 
0090       kArch->close ();
0091 
0092     }
0093   delete kArch;
0094 }
0095 
0096 /*
0097  *
0098  *  CompressTypeSelected is an integer and has to be acorrding with order in Dialog.qml
0099  *
0100  */
0101 bool CompressedFile::compress(const QVariantList &files, const QUrl &where, const QString &fileName, const int &compressTypeSelected)
0102 {
0103   bool error = true;
0104   assert(compressTypeSelected >= 0 && compressTypeSelected <= 8);
0105   for (const auto &uri : files) {
0106       qDebug() << "@gadominguez File:fm.cpp Funcion: compress  " << QUrl(uri.toString()).toLocalFile() << " " << fileName;
0107 
0108       if (!QFileInfo(QUrl(uri.toString()).toLocalFile()).isDir()) {
0109           auto file = QFile(QUrl(uri.toString()).toLocalFile());
0110           file.open(QIODevice::ReadWrite);
0111           if (file.isOpen() == true) {
0112               switch (compressTypeSelected) {
0113                 case 0: //.ZIP
0114                   {
0115                     auto kzip = new KZip(QUrl(where.toString() + "/" + fileName + ".zip").toLocalFile());
0116                     kzip->open(QIODevice::ReadWrite);
0117                     assert(kzip->isOpen() == true);
0118 
0119                     error = kzip->writeFile(uri.toString().remove(where.toString(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0120                                             file.readAll(),
0121                                             0100775,
0122                                             QFileInfo(file).owner(),
0123                                             QFileInfo(file).group(),
0124                                             QDateTime(),
0125                                             QDateTime(),
0126                                             QDateTime());
0127                     (void)kzip->close();
0128                     // WriteFile returns if the file was written or not,
0129                     // but this function returns if some error occurs so for this reason it is needed to toggle the value
0130                     error = !error;
0131                     break;
0132                   }
0133                 case 1: // .TAR
0134                   {
0135                     auto ktar = new KTar(QUrl(where.toString() + "/" + fileName + ".tar").toLocalFile());
0136                     ktar->open(QIODevice::ReadWrite);
0137                     assert(ktar->isOpen() == true);
0138                     error = ktar->writeFile(uri.toString().remove(where.toString(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0139                                             file.readAll(),
0140                                             0100775,
0141                                             QFileInfo(file).owner(),
0142                                             QFileInfo(file).group(),
0143                                             QDateTime(),
0144                                             QDateTime(),
0145                                             QDateTime());
0146                     (void)ktar->close();
0147                     break;
0148                   }
0149                 case 2: //.7ZIP
0150                   {
0151 #ifdef K7ZIP_H
0152 
0153                     // TODO: KArchive no permite comprimir ficheros del mismo modo que con TAR o ZIP. Hay que hacerlo de otra forma y requiere disponer de una libreria actualizada de KArchive.
0154                     auto k7zip = new K7Zip(QUrl(where.toString() + "/" + fileName + ".7z").toLocalFile());
0155                     k7zip->open(QIODevice::ReadWrite);
0156                     assert(k7zip->isOpen() == true);
0157                     error = k7zip->writeFile(uri.toString().remove(where.toString(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0158                                              file.readAll(),
0159                                              0100775,
0160                                              QFileInfo(file).owner(),
0161                                              QFileInfo(file).group(),
0162                                              QDateTime(),
0163                                              QDateTime(),
0164                                              QDateTime());
0165                     k7zip->close();
0166                     // WriteFile returns if the file was written or not,
0167                     // but this function returns if some error occurs so for this reason it is needed to toggle the value
0168                     error = !error;
0169 #endif
0170                     break;
0171                   }
0172                 case 3: //.AR
0173                   {
0174                     // TODO: KArchive no permite comprimir ficheros del mismo modo que con TAR o ZIP. Hay que hacerlo de otra forma y requiere disponer de una libreria actualizada de KArchive.
0175                     auto kar = new KAr(QUrl(where.toString() + "/" + fileName + ".ar").toLocalFile());
0176                     kar->open(QIODevice::ReadWrite);
0177                     assert(kar->isOpen() == true);
0178                     error = kar->writeFile(uri.toString().remove(where.toString(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0179                                            file.readAll(),
0180                                            0100775,
0181                                            QFileInfo(file).owner(),
0182                                            QFileInfo(file).group(),
0183                                            QDateTime(),
0184                                            QDateTime(),
0185                                            QDateTime());
0186                     (void)kar->close();
0187                     // WriteFile returns if the file was written or not,
0188                     // but this function returns if some error occurs so for this reason it is needed to toggle the value
0189                     error = !error;
0190                     break;
0191                   }
0192                 default:
0193                   qDebug() << "ERROR. COMPRESSED TYPE SELECTED NOT COMPATIBLE";
0194                   break;
0195                 }
0196             } else {
0197               qDebug() << "ERROR. CURRENT USER DOES NOT HAVE PEMRISSION FOR WRITE IN THE CURRENT DIRECTORY.";
0198               error = true;
0199             }
0200         } else {
0201           qDebug() << "Dir: " << QUrl(uri.toString()).toLocalFile();
0202           auto dir = QDirIterator(QUrl(uri.toString()).toLocalFile(), QDirIterator::Subdirectories);
0203           switch (compressTypeSelected) {
0204             case 0: //.ZIP
0205               {
0206                 auto kzip = new KZip(QUrl(where.toString() + "/" + fileName + ".zip").toLocalFile());
0207                 kzip->open(QIODevice::ReadWrite);
0208                 assert(kzip->isOpen() == true);
0209                 while (dir.hasNext()) {
0210                     auto entrie = dir.next();
0211 
0212                     qDebug() << entrie << " " << where.toString() << QFileInfo(entrie).isFile();
0213                     if (QFileInfo(entrie).isFile() == true) {
0214                         auto file = QFile(entrie);
0215                         file.open(QIODevice::ReadOnly);
0216                         qDebug() << entrie << entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive);
0217                         error = kzip->writeFile(entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0218                                                 file.readAll(),
0219                                                 0100775,
0220                                                 QFileInfo(file).owner(),
0221                                                 QFileInfo(file).group(),
0222                                                 QDateTime(),
0223                                                 QDateTime(),
0224                                                 QDateTime());
0225                         // WriteFile returns if the file was written or not,
0226                         // but this function returns if some error occurs so for this reason it is needed to toggle the value
0227                         error = !error;
0228                       }
0229                   }
0230                 (void)kzip->close();
0231                 break;
0232               }
0233             case 1: // .TAR
0234               {
0235                 auto ktar = new KTar(QUrl(where.toString() + "/" + fileName + ".tar").toLocalFile());
0236                 ktar->open(QIODevice::ReadWrite);
0237                 assert(ktar->isOpen() == true);
0238                 while (dir.hasNext()) {
0239                     auto entrie = dir.next();
0240 
0241                     qDebug() << entrie << " " << where.toString() << QFileInfo(entrie).isFile();
0242                     if (QFileInfo(entrie).isFile() == true) {
0243                         auto file = QFile(entrie);
0244                         file.open(QIODevice::ReadOnly);
0245                         qDebug() << entrie << entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive);
0246                         error = ktar->writeFile(entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0247                                                 file.readAll(),
0248                                                 0100775,
0249                                                 QFileInfo(file).owner(),
0250                                                 QFileInfo(file).group(),
0251                                                 QDateTime(),
0252                                                 QDateTime(),
0253                                                 QDateTime());
0254                         // WriteFile returns if the file was written or not,
0255                         // but this function returns if some error occurs so for this reason it is needed to toggle the value
0256                         error = !error;
0257                       }
0258                   }
0259                 (void)ktar->close();
0260                 break;
0261               }
0262             case 2: //.7ZIP
0263               {
0264 #ifdef K7ZIP_H
0265 
0266                 auto k7zip = new K7Zip(QUrl(where.toString() + "/" + fileName + ".7z").toLocalFile());
0267                 k7zip->open(QIODevice::ReadWrite);
0268                 assert(k7zip->isOpen() == true);
0269                 while (dir.hasNext()) {
0270                     auto entrie = dir.next();
0271 
0272                     qDebug() << entrie << " " << where.toString() << QFileInfo(entrie).isFile();
0273                     if (QFileInfo(entrie).isFile() == true) {
0274                         auto file = QFile(entrie);
0275                         file.open(QIODevice::ReadOnly);
0276                         qDebug() << entrie << entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive);
0277                         error = k7zip->writeFile(entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0278                                                  file.readAll(),
0279                                                  0100775,
0280                                                  QFileInfo(file).owner(),
0281                                                  QFileInfo(file).group(),
0282                                                  QDateTime(),
0283                                                  QDateTime(),
0284                                                  QDateTime());
0285                         // WriteFile returns if the file was written or not,
0286                         // but this function returns if some error occurs so for this reason it is needed to toggle the value
0287                         error = !error;
0288                       }
0289                   }
0290                 (void)k7zip->close();
0291 #endif
0292                 break;
0293               }
0294             case 3: //.AR
0295               {
0296                 auto kAr = new KAr(QUrl(where.toString() + "/" + fileName + ".ar").toLocalFile());
0297                 kAr->open(QIODevice::ReadWrite);
0298                 assert(kAr->isOpen() == true);
0299                 while (dir.hasNext()) {
0300                     auto entrie = dir.next();
0301 
0302                     qDebug() << entrie << " " << where.toString() << QFileInfo(entrie).isFile();
0303                     if (QFileInfo(entrie).isFile() == true) {
0304                         auto file = QFile(entrie);
0305                         file.open(QIODevice::ReadOnly);
0306                         qDebug() << entrie << entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive);
0307                         error = kAr->writeFile(entrie.remove(QUrl(where).toLocalFile(), Qt::CaseSensitivity::CaseSensitive), // Mirror file path in compressed file from current directory
0308                                                file.readAll(),
0309                                                0100775,
0310                                                QFileInfo(file).owner(),
0311                                                QFileInfo(file).group(),
0312                                                QDateTime(),
0313                                                QDateTime(),
0314                                                QDateTime());
0315                         // WriteFile returns if the file was written or not,
0316                         // but this function returns if some error occurs so for this reason it is needed to toggle the value
0317                         error = !error;
0318                       }
0319                   }
0320                 (void)kAr->close();
0321                 break;
0322               }
0323             default:
0324               qDebug() << "ERROR. COMPRESSED TYPE SELECTED NOT COMPATIBLE";
0325               break;
0326             }
0327         }
0328     }
0329 
0330   // kzip->prepareWriting("Hello00000.txt", "gabridc", "gabridc", 1024, 0100777, QDateTime(), QDateTime(), QDateTime());
0331   // kzip->writeData("Hello", sizeof("Hello"));
0332   // kzip->finishingWriting();
0333 
0334   return error;
0335 }
0336 
0337 KArchive *CompressedFile::getKArchiveObject(const QUrl &url)
0338 {
0339   KArchive *kArch = nullptr;
0340 
0341   /*
0342      * This checks depends on type COMPRESSED_MIMETYPES in file fmh.h
0343      */
0344   qDebug() << "@gadominguez File: fmstatic.cpp Func: getKArchiveObject MimeType: " << FMStatic::getMime(url);
0345 
0346   if (FMStatic::getMime(url).contains("application/x-tar") || FMStatic::getMime(url).contains("application/x-compressed-tar")) {
0347       kArch = new KTar(url.toString().split(QString("file://"))[1]);
0348     } else if (FMStatic::getMime(url).contains("application/zip")) {
0349       kArch = new KZip(url.toString().split(QString("file://"))[1]);
0350     } else if (FMStatic::getMime(url).contains("application/x-7z-compressed")) {
0351 #ifdef K7ZIP_H
0352       kArch = new K7Zip(url.toString().split(QString("file://"))[1]);
0353 #endif
0354     } else {
0355       qDebug() << "ERROR. COMPRESSED FILE TYPE UNKOWN " << url.toString();
0356     }
0357 
0358   return kArch;
0359 }
0360 
0361 void CompressedFile::setUrl(const QUrl &url)
0362 {
0363   if (m_url == url)
0364     return;
0365 
0366   m_url = url;
0367   Q_EMIT this->urlChanged();
0368 
0369   m_model->setUrl(m_url);
0370 }
0371 
0372 QUrl CompressedFile::url() const
0373 {
0374   return m_url;
0375 }
0376 
0377 CompressedFileModel *CompressedFile::model() const
0378 {
0379   return m_model;
0380 }