/*************************************************************************** * Copyright (C) 2004 by Raul Fernandes * * rgfbr@yahoo.com.br * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "p7zip.moc" using namespace KIO; kio_p7zipProtocol::kio_p7zipProtocol(const QCString &pool_socket, const QCString &app_socket) : SlaveBase("kio_p7zip", pool_socket, app_socket) { kdDebug() << "kio_p7zipProtocol::kio_p7zipProtocol()" << endl; p7zipProgram = KGlobal::dirs()->findExe( "7za" ); if( p7zipProgram.isNull() )// Check if 7za is available error( KIO::ERR_SLAVE_DEFINED, i18n( "The 7za binary was not found in PATH. You should install one of them to work with this kioslave" ) ); archive = 0; archiveTime = 0; } kio_p7zipProtocol::~kio_p7zipProtocol() { kdDebug() << "kio_p7zipProtocol::~kio_p7zipProtocol()" << endl; } void kio_p7zipProtocol::get(const KURL& url ) { kdDebug() << "kio_p7zip::get(const KURL& url)" << endl ; KURL archiveUrl; KURL fileUrl; if( !checkName( url, archiveUrl, fileUrl ) ) { // it is not a 7zip archive // send the path to konqueror to redirect to file:/ kioslave redirection( url.path() ); finished(); return; } proc1 = new KProcess(); processed = 0; connect( proc1, SIGNAL( receivedStdout( KProcess*, char*, int ) ), this, SLOT( receivedData( KProcess*, char*, int ) ) ); proc1->setEnvironment( "LC_ALL", KGlobal::locale()->language() ); *proc1 << p7zipProgram << "e" << "-so" << "-bd" << "-y" << archiveUrl.path() << fileUrl.path().remove( 0, 1 ); infoMessage( i18n( "Unpacking file..." ) ); proc1->start( KProcess::Block, KProcess::AllOutput ); if( !proc1->normalExit() ) error( KIO::ERR_CANNOT_LAUNCH_PROCESS, url.path() ); else if( proc1->exitStatus() != 0 ) error( KIO::ERR_SLAVE_DEFINED, i18n( "A error occurred when unpacking %1" ).arg( url.path() ) ); data( QByteArray() ); // empty array means we're done sending the data finished(); delete proc1; proc1 = 0; } //void kio_p7zipProtocol::mimetype(const KURL & /*url*/) /*{ mimeType("text/plain"); finished(); }*/ extern "C" { int kdemain(int argc, char **argv) { KInstance instance( "kio_p7zip" ); kdDebug() << "*** Starting kio_p7zip " << endl; if (argc != 4) { kdDebug() << "Usage: kio_p7zip protocol domain-socket1 domain-socket2" << endl; exit(-1); } kio_p7zipProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); kdDebug() << "*** kio_p7zip Done" << endl; return 0; } } /*! \fn kio_p7zipProtocol::receivedData( KProcess *, char* buffer, int len ) */ void kio_p7zipProtocol::receivedData( KProcess *, char* buffer, int len ) { QByteArray d(len); d.setRawData(buffer,len); data(d); d.resetRawData(buffer,len); processed += len; processedSize( processed ); } /*! \fn kio_p7zipProtocol::checkName( const KURL &url, KURL &archiveUrl, KURL &fileUrl ) */ bool kio_p7zipProtocol::checkName( const KURL &url, KURL &archiveUrl, KURL &fileUrl ) { if( url.path().find( ".7z", false ) == -1 ) return false; archiveUrl = url.path().section( ".7z", 0, 0 ) + ".7z"; if( url.path().endsWith( ".7z" ) ) fileUrl = "/"; else fileUrl = url.path().section( ".7z", 1 ); return true; } /*! \fn kio_p7zipProtocol::stat( const KURL & url ) */ void kio_p7zipProtocol::stat( const KURL & url ) { KURL archiveUrl; KURL fileUrl; if( !checkName( url, archiveUrl, fileUrl ) ) { // it is not a 7zip archive // send the path to konqueror to redirect to file:/ kioslave redirection( url.path() ); finished(); return; } //messageBox( Information, QString( "stat\nurl: %1"/*\ndir: %2\nfileName: %3\nfile: %4"*/ ).arg( /*archiveName*/url.path() )/*.arg( dirName ).arg( fileName ).arg( file )*/ ); UDSEntry entry; UDSAtom atom; // check if it is root directory if( fileUrl.path() == "/" ) { atom.m_uds = KIO::UDS_NAME; atom.m_str = "/"; entry.append(atom); atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFDIR; entry.append(atom); statEntry(entry); finished(); return; } listArchive( archiveUrl ); QString linha; const QString file = fileUrl.path( -1 ).remove( 0, 1 ); QString fileName; for( QStringList::Iterator it = archiveList.begin(); it != archiveList.end(); ++it ) { linha = *it; if( linha.find( "----" ) != -1 ) { error( KIO::ERR_DOES_NOT_EXIST, url.path() ); return; } fileName = linha.mid( 53 ).stripWhiteSpace(); if( fileName == file ) break; } // name of file atom.m_uds = KIO::UDS_NAME; atom.m_str = fileName.section( '\\', -1 ); entry.append(atom); QStringList list = QStringList::split( ' ', linha ); // type of file fileName = list[ 2 ]; if( fileName[ 0 ] == 'D' ) { atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFDIR; entry.append( atom ); }else { atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFREG; entry.append( atom ); } // size atom.m_uds = KIO::UDS_SIZE; atom.m_long = list[ 3 ].toLong(); entry.append(atom); statEntry(entry); finished(); } /*! \fn kio_p7zipProtocol::listDir( const KURL & url ) */ void kio_p7zipProtocol::listDir( const KURL & url ) { KURL archiveUrl; KURL fileUrl; if( !checkName( url, archiveUrl, fileUrl ) ) { // it is not a 7zip archive // send the path to konqueror to redirect to file:/ kioslave redirection( url.path() ); finished(); return; } //messageBox( Information, QString( "listDir\nurl: %1\ndir: %2\nprogram: %3" ).arg( archiveUrl.path() ).arg( archiveUrl.path() ).arg( p7zipProgram ) );//.arg( fileName ).arg( file ) ); infoMessage( i18n( "Listing directory..." ) ); listArchive( archiveUrl ); UDSEntry entry; UDSAtom atom; int pos; QString linha; const QString file = fileUrl.path( -1 ).remove( 0, 1 ); QString fileName; for( QStringList::Iterator it = archiveList.begin(); it != archiveList.end(); ++it ) { linha = *it; if( linha.find( "----" ) != -1 ) break; entry.clear(); fileName = linha.mid( 53 ).stripWhiteSpace(); kdDebug() << "listDir\nlinha: " << fileName << endl; if( !file.isEmpty() ) if( fileName.find( file ) == 0 ) { if( fileName == file ) continue; fileName = fileName.mid( file.length() + 1 ); }else continue; pos = fileName.find( '/' ); if( pos != -1 ) continue; // name of file atom.m_uds = KIO::UDS_NAME; atom.m_str = fileName.section( '/', -1 ); entry.append(atom); QStringList list = QStringList::split( ' ', linha ); // type of file fileName = list[ 2 ]; if( fileName[ 0 ] == 'D' ) { atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFDIR; entry.append( atom ); }else { atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFREG; entry.append( atom ); } // size atom.m_uds = KIO::UDS_SIZE; atom.m_long = list[ 3 ].toLong(); entry.append(atom); // time atom.m_uds = KIO::UDS_MODIFICATION_TIME; QDate date( list[ 0 ].mid( 0, 4 ).toInt(), list[ 0 ].mid( 5, 2 ).toInt(), list[ 0 ].mid( 8, 2 ).toInt() ); QTime time( list[ 1 ].mid( 0, 2 ).toInt(), list[ 1 ].mid( 3, 2 ).toInt(), list[ 1 ].mid( 6, 2 ).toInt() ); atom.m_long = QDateTime( date, time ).toTime_t(); entry.append(atom); // send entry listEntry(entry, false); } listEntry( entry, true); finished(); } /*! \fn kio_p7zipProtocol::put(const KURL& url,int permissions,bool overwrite,bool resume) */ void kio_p7zipProtocol::put(const KURL& url,int /*permissions*/,bool /*overwrite*/,bool /*resume*/) { KURL archiveUrl; KURL fileUrl; if( !checkName( url, archiveUrl, fileUrl ) ) { // it is not a 7zip archive // return the error that cannot enter the directory error(ERR_CANNOT_ENTER_DIRECTORY,url.path()); return; } infoMessage( i18n( "Adding file..." ) ); //messageBox( Information, QString( "put\nurl: %1\narchiveUrl: %2\nfileUrl: %3" ).arg( url.path() ).arg( archiveUrl.path() ).arg( fileUrl.path().remove( 0, 1 ) ) ); // receive the data QByteArray buffer; int length; QFile file( "/tmp/" + fileUrl.fileName() ); file.open( IO_WriteOnly ); do { dataReq(); length = readData( buffer ); file.writeBlock( buffer ); }while( length > 0 ); file.close(); proc = new KProcIO(); //proc->setUseShell( true );//-t7z -m0=lzma proc->setEnvironment( "LC_ALL", KGlobal::locale()->language() ); *proc << p7zipProgram << "a" << archiveUrl.path() << file.name(); proc->start( KProcess::Block, KProcess::NoCommunication ); if( !proc->normalExit() ) error( KIO::ERR_CANNOT_LAUNCH_PROCESS, url.path() ); else if( proc->exitStatus() != 0 ) error( KIO::ERR_SLAVE_DEFINED, i18n( "A error occurred when adding %1" ).arg( url.path() ) ); //delete the temporary file file.remove(); delete proc; proc = 0; finished(); } /*! \fn kio_p7zipProtocol::listArchive( const KURL &archiveUrl ) */ bool kio_p7zipProtocol::listArchive( const KURL &archiveUrl ) { if( archive == archiveUrl ) { // Has it changed ? struct stat statbuf; if ( ::stat( QFile::encodeName( archiveUrl.path() ), &statbuf ) == 0 ) { if ( archiveTime == statbuf.st_mtime ) return true; } } archive = archiveUrl; proc = new KProcIO(); proc->setEnvironment( "LC_ALL", KGlobal::locale()->language() ); *proc << p7zipProgram << "l" << archive.path(); proc->start( KProcess::Block ); //if( !proc->normalExit() ) error( KIO::ERR_CANNOT_LAUNCH_PROCESS, archive.path() ); archiveList.clear(); QString linha; while( proc->readln( linha ) != -1 ) if( linha.find( "----" ) != -1 ) break; while( proc->readln( linha ) != -1 ) { if( linha.find( "----" ) != -1 ) break; archiveList.append( linha ); } delete proc; proc = 0; return true; } /*! \fn kio_p7zipProtocol::del( const KURL &url, bool isFile ) */ void kio_p7zipProtocol::del( const KURL &url, bool /*isFile*/ ) { KURL archiveUrl; KURL fileUrl; if( !checkName( url, archiveUrl, fileUrl ) ) { // it is not a 7zip archive // return the error that cannot enter the directory error(ERR_CANNOT_ENTER_DIRECTORY,url.path()); return; } infoMessage( i18n( "Deleting file..." ) ); //messageBox( Information, QString( "del\nurl: %1\narchiveUrl: %2\nfileUrl: %3" ).arg( url.path() ).arg( archiveUrl.path() ).arg( fileUrl.path().remove( 0, 1 ) ) ); proc1 = new KProcess(); proc1->setUseShell( true ); proc1->setEnvironment( "LC_ALL", KGlobal::locale()->language() ); *proc1 << p7zipProgram << "d" << "\"" + archiveUrl.path() + "\"" << "\"" + fileUrl.path().remove( 0, 1 ) + "\""; proc1->start( KProcess::Block, KProcess::NoCommunication ); if( !proc1->normalExit() ) error( KIO::ERR_CANNOT_LAUNCH_PROCESS, url.path() ); else if( proc1->exitStatus() != 0 ) error( KIO::ERR_SLAVE_DEFINED, i18n( "A error occurred when deleting %1" ).arg( url.path() ) ); finished(); }