/*************************************************************************** krarchandler.cpp ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // QT includes #include // KDE includes #include #include #include #include #include #include #include #include #include // Krusader includes #include "krarchandler.h" #include "../krusader.h" #include "../defaults.h" #include "../krservices.h" #include "../Dialogs/krpleasewait.h" static TQStringList arcProtocols = TQStringList::split(";", "tar;bzip;bzip2;gzip;krarc;zip"); TDEWallet::Wallet * KRarcHandler::wallet = 0; TQStringList KRarcHandler::supportedPackers() { TQStringList packers; // we will simply try to find the packers here.. if ( KrServices::cmdExist( "tar" ) ) packers.append( "tar" ); if ( KrServices::cmdExist( "gzip" ) ) packers.append( "gzip" ); if ( KrServices::cmdExist( "bzip2" ) ) packers.append( "bzip2" ); if ( KrServices::cmdExist( "unzip" ) ) packers.append( "unzip" ); if ( KrServices::cmdExist( "zip" ) ) packers.append( "zip" ); if ( KrServices::cmdExist( "lha" ) ) packers.append( "lha" ); if ( KrServices::cmdExist( "cpio" ) ) packers.append( "cpio" ); if ( KrServices::cmdExist( "unrar" ) ) packers.append( "unrar" ); if ( KrServices::cmdExist( "rar" ) ) packers.append( "rar" ); if ( KrServices::cmdExist( "arj" ) ) packers.append( "arj" ); if ( KrServices::cmdExist( "unarj" ) ) packers.append( "unarj" ); if ( KrServices::cmdExist( "unace" ) ) packers.append( "unace" ); if ( KrServices::cmdExist( "dpkg" ) ) packers.append( "dpkg" ); if ( KrServices::cmdExist( "7z" ) || KrServices::cmdExist( "7za" ) ) packers.append( "7z" ); if ( KrServices::cmdExist( "rpm" ) && KrServices::cmdExist( "rpm2cpio" ) ) packers.append( "rpm" ); // kdDebug() << "Supported Packers:" << endl; //TQStringList::Iterator it; //for( it = packers.begin(); it != packers.end(); ++it ) // kdDebug() << *it << endl; return packers; } bool KRarcHandler::arcSupported( TQString type ) { // lst will contain the supported unpacker list... krConfig->setGroup( "Archives" ); TQStringList lst = krConfig->readListEntry( "Supported Packers" ); if ( type == "-zip" && lst.contains( "unzip" ) ) return true; else if ( type == "-tar" && lst.contains( "tar" ) ) return true; else if ( type == "-tbz" && lst.contains( "tar" ) ) return true; else if ( type == "-tgz" && lst.contains( "tar" ) ) return true; else if ( type == "tarz" && lst.contains( "tar" ) ) return true; else if ( type == "gzip" && lst.contains( "gzip" ) ) return true; else if ( type == "zip2" && lst.contains( "bzip2" ) ) return true; else if ( type == "-lha" && lst.contains( "lha" ) ) return true; else if ( type == "-ace" && lst.contains( "unace" ) ) return true; else if ( type == "-rpm" && lst.contains( "cpio" ) ) return true; else if ( type == "cpio" && lst.contains( "cpio" ) ) return true; else if ( type == "-rar" && ( lst.contains( "unrar" ) || lst.contains( "rar" ) ) ) return true; else if ( type == "-arj" && ( lst.contains( "unarj" ) || lst.contains( "arj" ) ) ) return true; else if ( type == "-deb" && ( lst.contains( "dpkg" ) && lst.contains( "tar" ) ) ) return true; else if ( type == "-7z" && lst.contains( "7z" ) ) return true; // not supported : ( return false; } bool KRarcHandler::arcHandled( TQString type ) { // first check if supported if ( !arcSupported( type ) ) return false; krConfig->setGroup( "Archives" ); if ( ( type == "-tgz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) || ( type == "tarz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) || ( type == "-tar" && krConfig->readBoolEntry( "Do Tar" , _DoTar ) ) || ( type == "-tbz" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) || ( type == "gzip" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) || ( type == "zip2" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) || ( type == "-zip" && krConfig->readBoolEntry( "Do UnZip", _DoUnZip ) ) || ( type == "-lha" && krConfig->readBoolEntry( "Do Lha", _DoUnZip ) ) || ( type == "-rar" && krConfig->readBoolEntry( "Do UnRar", _DoUnRar ) ) || ( type == "-arj" && krConfig->readBoolEntry( "Do UnArj", _DoUnarj ) ) || ( type == "-ace" && krConfig->readBoolEntry( "Do UnAce", _DoUnAce ) ) || ( type == "cpio" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) || ( type == "-rpm" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) || ( type == "-deb" && krConfig->readBoolEntry( "Do DEB" , _DoDEB ) ) || ( type == "-7z" && krConfig->readBoolEntry( "Do 7z" , _Do7z ) ) ) return true; else return false; } long KRarcHandler::arcFileCount( TQString archive, TQString type, TQString password ) { int divideWith = 1; // first check if supported if ( !arcSupported( type ) ) return 0; // bzip an gzip archive contains only one file if ( type == "zip2" || type == "gzip" ) return 1L; // set the right lister to do the job TQString lister; if ( type == "-zip" ) lister = KrServices::fullPathName( "unzip" ) + " -ZTs"; else if ( type == "-tar" ) lister = KrServices::fullPathName( "tar" ) + " -tvf"; else if ( type == "-tgz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf"; else if ( type == "tarz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf"; else if ( type == "-tbz" ) lister = KrServices::fullPathName( "tar" ) + " -tjvf"; else if ( type == "-lha" ) lister = KrServices::fullPathName( "lha" ) + " l"; else if ( type == "-rar" ) lister = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " l -v"; else if ( type == "-ace" ) lister = KrServices::fullPathName( "unace" ) + " l"; else if ( type == "-arj" ) { if( KrServices::cmdExist( "arj" ) ) lister = KrServices::fullPathName( "arj" ) + " v -y -v", divideWith = 4; else lister = KrServices::fullPathName( "unarj" ) + " l"; } else if ( type == "-rpm" ) lister = KrServices::fullPathName( "rpm" ) + " --dump -lpq"; else if ( type == "-deb" ) lister = KrServices::fullPathName( "dpkg" ) + " -c"; else if ( type == "-7z" ) lister = KrServices::fullPathName( "7z" ) + " -y l"; else return 0L; if ( !password.isNull() ) { if ( type == "-arj" ) lister += " -g'" + password + "'"; if ( type == "-ace" || type == "-rar" || type == "-7z" ) lister += " -p'" + password + "'"; } // tell the user to wait krApp->startWaiting( i18n( "Counting files in archive" ), 0, true ); // count the number of files in the archive long count = 1; KTempFile tmpFile( /*"tmp"*/ TQString(), "krusader-unpack" ); // commented out as it created files in the current dir! KrShellProcess list; list << lister << KrServices::quote( archive ) << ">" << tmpFile.name() ; if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!! list<< "<" << "/dev/ptmx"; list.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ); while ( list.isRunning() ) { usleep( 1000 ); tqApp->processEvents(); if( krApp->wasWaitingCancelled() ) list.kill(); } ; // busy wait - need to find something better... krApp->stopWait(); if( !list.normalExit() || !checkStatus( type, list.exitStatus() ) ) { KMessageBox::detailedError (krApp, i18n( "Failed to list the content of the archive (%1)!" ).arg( archive ), list.getErrorMsg(), i18n("Error" ) ); return 0; } TQTextStream *stream = tmpFile.textStream(); while ( stream && stream->readLine() != TQString() ) ++count; tmpFile.unlink(); //make sure you call stopWait after this function return... //krApp->stopWait(); return count / divideWith; } bool KRarcHandler::unpack( TQString archive, TQString type, TQString password, TQString dest ) { krConfig->setGroup( "Archives" ); if ( krConfig->readBoolEntry( "Test Before Unpack", _TestBeforeUnpack ) ) { // test first - or be sorry later... if ( type != "-rpm" && type != "-deb" && !test( archive, type, password, 0 ) ) { KMessageBox::error( krApp, i18n( "Failed to unpack" ) + " \"" + archive + "\" !" ); return false; } } // count the files in the archive long count = arcFileCount( archive, type, password ); if ( count == 0 ) return false; // not supported if ( count == 1 ) count = 0 ; // choose the right packer for the job TQString packer, cpioName = TQString(); // set the right packer to do the job if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -o" ; else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -xvf"; else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf"; else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf"; else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -xjvf"; else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -cd"; else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -cdk"; else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " xf"; else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " -y x"; else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " x"; else if ( type == "-arj" ) packer = KrServices::cmdExist( "arj" ) ? KrServices::fullPathName( "arj" ) + " -y -v x" : KrServices::fullPathName( "unarj" ) + " x"; else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y x"; else if ( type == "-rpm" ) { TQString tempDir = locateLocal("tmp",TQString()); cpioName = tempDir+"/contents.cpio"; KrShellProcess cpio; cpio << KrServices::fullPathName( "rpm2cpio" ) << " " + KrServices::quote( archive ) << " > " << cpioName; cpio.start(TDEProcess::Block, TDEProcess::AllOutput ); if( !cpio.normalExit() || !checkStatus( "cpio", cpio.exitStatus() ) ) { KMessageBox::detailedError (krApp, i18n( "Failed to convert rpm (%1) to cpio!" ).arg( archive ), cpio.getErrorMsg(), i18n("Error" ) ); return 0; } archive = cpioName; packer = KrServices::fullPathName( "cpio" ) + " --force-local --no-absolute-filenames -iuvdF"; } else if ( type == "-deb" ) { TQString tempDir = locateLocal("tmp",TQString()); cpioName = tempDir+"/contents.tar"; KrShellProcess dpkg; dpkg << KrServices::fullPathName( "dpkg" ) << " --fsys-tarfile " + KrServices::quote( archive ) << " > " << cpioName; dpkg.start(TDEProcess::Block, TDEProcess::AllOutput ); if( !dpkg.normalExit() || !checkStatus( "-deb", dpkg.exitStatus() ) ) { KMessageBox::detailedError (krApp, i18n( "Failed to convert deb (%1) to tar!" ).arg( archive ), dpkg.getErrorMsg(), i18n("Error" ) ); return 0; } archive = cpioName; packer = KrServices::fullPathName( "tar" ) + " xvf "; } else return false; if ( !password.isNull() ) { if ( type == "-zip" ) packer += " -P '" + password + "'"; if ( type == "-arj" ) packer += " -g'" + password + "'"; if ( type == "-ace" || type == "-rar" || type == "-7z" ) packer += " -p'" + password + "'"; } // unpack the files KrShellProcess proc; proc << packer << " " + KrServices::quote( archive ); if( type == "zip2" || type=="gzip" ){ TQString arcname = archive.mid(archive.findRev("/")+1); if( arcname.contains(".") ) arcname = arcname.left(arcname.findRev(".")); proc << ">" << KrServices::quote( dest+"/"+arcname ); } if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!! proc << "<" << "/dev/ptmx"; TQString save = getcwd( 0, 0 ); chdir( dest.local8Bit() ); // tell the user to wait krApp->startWaiting( i18n( "Unpacking File(s)" ), count, true ); if ( count != 0 ) { connect( &proc, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ), krApp, TQT_SLOT( incProgress( TDEProcess*, char*, int ) ) ); if( type == "-rpm" ) connect( &proc, TQT_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ), krApp, TQT_SLOT( incProgress( TDEProcess*, char*, int ) ) ); } // start the unpacking process proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ); while ( proc.isRunning() ) { usleep( 1000 ); tqApp->processEvents(); if( krApp->wasWaitingCancelled() ) proc.kill(); } ; // busy wait - need to find something better... krApp->stopWait(); chdir( save.local8Bit() ); if( !cpioName.isEmpty() ) TQFile( cpioName ).remove(); /* remove the cpio file */ // check the return value if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) { KMessageBox::detailedError (krApp, i18n( "Failed to unpack %1!" ).arg( archive ), krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) : proc.getErrorMsg(), i18n("Error" ) ); return false; } return true; // SUCCESS } bool KRarcHandler::test( TQString archive, TQString type, TQString password, long count ) { // choose the right packer for the job TQString packer; // set the right packer to do the job if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -t"; else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -tvf"; else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf"; else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf"; else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -tjvf"; else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -tv"; else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -tv"; else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " t"; else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " t"; else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " t"; else if ( type == "-arj" ) packer = KrServices::fullPathName( KrServices::cmdExist( "arj" ) ? "arj" : "unarj" ) + " t"; else if ( type == "cpio" ) packer = KrServices::fullPathName( "cpio" ) + " --only-verify-crc -tvF" ; else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y t"; else return false; if ( !password.isNull() ) { if ( type == "-zip" ) packer += " -P '" + password + "'"; if ( type == "-arj" ) packer += " -g'" + password + "'"; if ( type == "-ace" || type == "-rar" || type == "-7z" ) packer += " -p'" + password + "'"; } // unpack the files KrShellProcess proc; proc << packer << KrServices::quote( archive ); if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!! proc << "<" << "/dev/ptmx"; // tell the user to wait krApp->startWaiting( i18n( "Testing Archive" ), count, true ); if ( count != 0 ) connect( &proc, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ), krApp, TQT_SLOT( incProgress( TDEProcess*, char*, int ) ) ); // start the unpacking process proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ); while ( proc.isRunning() ) { usleep( 1000 ); tqApp->processEvents(); if( krApp->wasWaitingCancelled() ) proc.kill(); } ; // busy wait - need to find something better... krApp->stopWait(); // check the return value if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) return false; return true; // SUCCESS } bool KRarcHandler::pack( TQStringList fileNames, TQString type, TQString dest, long count, TQMap extraProps ) { // set the right packer to do the job TQString packer; if ( type == "zip" ) { packer = KrServices::fullPathName( "zip" ) + " -ry"; type = "-zip"; } else if ( type == "tar" ) { packer = KrServices::fullPathName( "tar" ) + " -cvf"; type = "-tar"; } else if ( type == "tar.gz" ) { packer = KrServices::fullPathName( "tar" ) + " -cvzf"; type = "-tgz"; } else if ( type == "tar.bz2" ) { packer = KrServices::fullPathName( "tar" ) + " -cvjf"; type = "-tbz"; } else if ( type == "rar" ) { packer = KrServices::fullPathName( "rar" ) + " -r a"; type = "-rar"; } else if ( type == "lha" ) { packer = KrServices::fullPathName( "lha" ) + " a"; type = "-lha"; } else if ( type == "arj" ) { packer = KrServices::fullPathName( "arj" ) + " -r -y a"; type = "-arj"; } else if ( type == "7z" ) { packer = KrServices::fullPathName( "7z" ) + " -y a"; type = "-7z"; } else return false; TQString password = TQString(); if( extraProps.count( "Password" ) > 0 ) { password = extraProps[ "Password" ]; if ( !password.isNull() ) { if ( type == "-zip" ) packer += " -P '" + password + "'"; else if ( type == "-arj" ) packer += " -g'" + password + "'"; else if ( type == "-ace" || type == "-7z" ) packer += " -p'" + password + "'"; else if ( type == "-rar" ) { if( extraProps.count( "EncryptHeaders" ) > 0 ) packer += " -hp'" + password + "'"; else packer += " -p'" + password + "'"; } else password = TQString(); } } if( extraProps.count( "VolumeSize" ) > 0 ) { TQString sizeStr = extraProps[ "VolumeSize" ]; TDEIO::filesize_t size = sizeStr.toLongLong(); if( size >= 10000 ) { if( type == "-arj" || type == "-rar" ) packer += TQString( " -v%1b" ).arg( sizeStr ); } } if( extraProps.count( "CompressionLevel" ) > 0 ) { int level = extraProps[ "CompressionLevel" ].toInt() - 1; if ( level < 0 ) level = 0; if ( level > 8 ) level = 8; if( type == "-rar" ) { static const int rarLevels[] = { 0, 1, 2, 2, 3, 3, 4, 4, 5 }; packer += TQString( " -m%1" ).arg( rarLevels[ level ] ); } else if( type == "-arj" ) { static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 }; packer += TQString( " -m%1" ).arg( arjLevels[ level ] ); } else if( type == "-zip" ) { static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer += TQString( " -%1" ).arg( zipLevels[ level ] ); } else if( type == "-7z" ) { static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer += TQString( " -mx%1" ).arg( sevenZipLevels[ level ] ); } } if( extraProps.count( "CommandLineSwitches" ) > 0 ) packer += TQString( " %1" ).arg( extraProps[ "CommandLineSwitches" ] ); // prepare to pack KrShellProcess proc; proc << packer << KrServices::quote( dest ); for ( TQStringList::Iterator file = fileNames.begin(); file != fileNames.end(); ++file ) { proc << KrServices::quote( *file ); } // tell the user to wait krApp->startWaiting( i18n( "Packing File(s)" ), count, true ); if ( count != 0 ) connect( &proc, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ), krApp, TQT_SLOT( incProgress( TDEProcess*, char*, int ) ) ); // start the packing process proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ); while ( proc.isRunning() ) { usleep( 1000 ); tqApp->processEvents(); if( krApp->wasWaitingCancelled() ) proc.kill(); } ; // busy wait - need to find something better... krApp->stopWait(); // check the return value if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) { KMessageBox::detailedError (krApp, i18n( "Failed to pack %1!" ).arg( dest ), krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) : proc.getErrorMsg(), i18n("Error" ) ); return false; } krConfig->setGroup( "Archives" ); if ( krConfig->readBoolEntry( "Test Archives", _TestArchives ) && !test( dest, type, password, count ) ) { KMessageBox::error( krApp, i18n( "Failed to pack: " ) + dest, i18n( "Error" ) ); return false; } return true; // SUCCESS } TQString KRarcHandler::getPassword( TQString path ) { TQString password; TQString key = "krarc-" + path; if( !TDEWallet::Wallet::keyDoesNotExist(TDEWallet::Wallet::NetworkWallet(), TDEWallet::Wallet::PasswordFolder(), key ) ) { if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) { delete wallet; wallet = 0; } if( wallet == 0 ) wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() ); if ( wallet && wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) ) { wallet->setFolder( TDEWallet::Wallet::PasswordFolder() ); TQMap map; if ( wallet->readMap( key, map ) == 0 ) { TQMap::ConstIterator it = map.find( "password" ); if ( it != map.end() ) password = it.data(); } } } bool keep = true; TQString user = "archive"; TDEIO::PasswordDialog passDlg( i18n("This archive is encrypted, please supply the password:"), user, true ); passDlg.setPassword( password ); if (passDlg.exec() == TDEIO::PasswordDialog::Accepted) { password = passDlg.password(); if ( keep ) { if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) { delete wallet; wallet = 0; } if ( !wallet ) wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() ); if ( wallet ) { bool ok = true; if ( !wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) ) ok = wallet->createFolder( TDEWallet::Wallet::PasswordFolder() ); if ( ok ) { wallet->setFolder( TDEWallet::Wallet::PasswordFolder() ); TQMap map; map.insert( "login", "archive" ); map.insert( "password", password ); wallet->writeMap( key, map ); } } } return password; } return ""; } bool KRarcHandler::isArchive(const KURL& url) { TQString protocol = url.protocol(); if (arcProtocols.find(protocol) != arcProtocols.end()) return true; else return false; } TQString KRarcHandler::getType( bool &encrypted, TQString fileName, TQString mime, bool checkEncrypted ) { TQString result = detectArchive( encrypted, fileName, checkEncrypted ); if( result.isNull() ) result = mime; else result = "-" + result; if( result.endsWith( "-7z" ) ) result = "-7z"; return result.right( 4 ); } bool KRarcHandler::checkStatus( TQString type, int exitCode ) { if( type == "-zip" || type == "-rar" || type == "-7z" ) return exitCode == 0 || exitCode == 1; else if( type == "-ace" || type == "zip2" || type == "-lha" || type == "-rpm" || type == "cpio" || type == "-tar" || type == "tarz" || type == "-tbz" || type == "-tgz" || type == "-arj" || type == "-deb" ) return exitCode == 0; else if( type == "gzip" ) return exitCode == 0 || exitCode == 2; else return exitCode == 0; } struct AutoDetectParams { TQString type; int location; TQString detectionString; }; TQString KRarcHandler::detectArchive( bool &encrypted, TQString fileName, bool checkEncrypted ) { static AutoDetectParams autoDetectParams[] = {{"zip", 0, "PK\x03\x04"}, {"rar", 0, "Rar!\x1a" }, {"arj", 0, "\x60\xea" }, {"rpm", 0, "\xed\xab\xee\xdb"}, {"ace", 7, "**ACE**" }, {"bzip2",0, "\x42\x5a\x68\x39\x31" }, {"gzip", 0, "\x1f\x8b"}, {"deb", 0, "!\ndebian-binary " }, {"7z", 0, "7z\xbc\xaf\x27\x1c" } }; static int autoDetectElems = sizeof( autoDetectParams ) / sizeof( AutoDetectParams ); encrypted = false; TQFile arcFile( fileName ); if ( arcFile.open( IO_ReadOnly ) ) { char buffer[ 1024 ]; long sizeMax = arcFile.readBlock( buffer, sizeof( buffer ) ); arcFile.close(); for( int i=0; i < autoDetectElems; i++ ) { TQString detectionString = autoDetectParams[ i ].detectionString; int location = autoDetectParams[ i ].location; int endPtr = detectionString.length() + location; if( endPtr > sizeMax ) continue; unsigned int j=0; for(; j != detectionString.length(); j++ ) { if( detectionString[ j ] == '?' ) continue; if( buffer[ location + j ] != detectionString[ j ] ) break; } if( j == detectionString.length() ) { TQString type = autoDetectParams[ i ].type; if( type == "bzip2" || type == "gzip" ) { KTar tapeArchive( fileName ); if( tapeArchive.open( IO_ReadOnly ) ) { tapeArchive.close(); if( type == "bzip2" ) type = "tbz"; else type = "tgz"; } } else if( type == "zip" ) encrypted = (buffer[6] & 1); else if( type == "arj" ) { if( sizeMax > 4 ) { long headerSize = ((unsigned char *)buffer)[ 2 ] + 256*((unsigned char *)buffer)[ 3 ]; long fileHeader = headerSize + 10; if( fileHeader + 9 < sizeMax && buffer[ fileHeader ] == (char)0x60 && buffer[ fileHeader + 1 ] == (char)0xea ) encrypted = (buffer[ fileHeader + 8 ] & 1 ); } } else if( type == "rar" ) { if( sizeMax > 13 && buffer[ 9 ] == (char)0x73 ) { if( buffer[ 10 ] & 0x80 ) { // the header is encrypted? encrypted = true; } else { long offset = 7; long mainHeaderSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ]; offset += mainHeaderSize; while( offset + 10 < sizeMax ) { long headerSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ]; bool isDir = (buffer[ offset+7 ] == '\0' ) && (buffer[ offset+8 ] == '\0' ) && (buffer[ offset+9 ] == '\0' ) && (buffer[ offset+10 ] == '\0' ); if( buffer[ offset + 2 ] != (char)0x74 ) break; if( !isDir ) { encrypted = ( buffer[ offset + 3 ] & 4 ) != 0; break; } offset += headerSize; } } } } else if( type == "ace" ) { long offset = 0; long mainHeaderSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4; offset += mainHeaderSize; while( offset + 10 < sizeMax ) { long headerSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4; bool isDir = (buffer[ offset+11 ] == '\0' ) && (buffer[ offset+12 ] == '\0' ) && (buffer[ offset+13 ] == '\0' ) && (buffer[ offset+14 ] == '\0' ); if( buffer[ offset + 4 ] != (char)0x01 ) break; if( !isDir ) { encrypted = ( buffer[ offset + 6 ] & 64 ) != 0; break; } offset += headerSize; } } else if( type == "7z" ) { if( checkEncrypted ) { // encryption check is expensive // check only if it's necessary Kr7zEncryptionChecker proc; proc << KrServices::fullPathName( "7z" ) << " -y t"; proc << KrServices::quote( fileName ); proc.start(TDEProcess::Block,TDEProcess::AllOutput); encrypted = proc.isEncrypted(); } } return type; } } if( sizeMax >= 512 ) { /* checking if it's a tar file */ unsigned checksum = 32*8; char chksum[ 9 ]; for( int i=0; i != 512; i++ ) checksum += ((unsigned char *)buffer)[ i ]; for( int i=148; i != 156; i++ ) checksum -= ((unsigned char *)buffer)[ i ]; sprintf( chksum, "0%o", checksum ); if( !memcmp( buffer + 148, chksum, strlen( chksum ) ) ) { int k = strlen( chksum ); for(; k < 8; k++ ) if( buffer[148+k] != 0 && buffer[148+k] != 32 ) break; if( k==8 ) return "tar"; } } } return TQString(); } #include "krarchandler.moc"