/*************************************************************************** * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com * * Please do not use email address above for bug reports; see * * the README file * * * * 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., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "msits.h" #include "libchmurlfactory.h" using namespace KIO; extern "C" { int kdemain( int argc, char **argv ) { kdDebug() << "*** kio_msits Init" << endl; KInstance instance( "kio_msits" ); if ( argc != 4 ) { kdDebug() << "Usage: kio_msits protocol domain-socket1 domain-socket2" << endl; exit (-1); } ProtocolMSITS slave ( argv[2], argv[3] ); slave.dispatchLoop(); kdDebug() << "*** kio_msits Done" << endl; return 0; } } ProtocolMSITS::ProtocolMSITS (const QCString &pool_socket, const QCString &app_socket) : SlaveBase ("kio_msits", pool_socket, app_socket) { m_chmFile = 0; } ProtocolMSITS::~ProtocolMSITS() { if ( !m_chmFile ) return; chm_close (m_chmFile); m_chmFile = 0; } // A simple stat() wrapper static bool isDirectory ( const QString & filename ) { return filename[filename.length() - 1] == '/'; } void ProtocolMSITS::get( const KURL& url ) { QString htmdata, fileName; chmUnitInfo ui; QByteArray buf; kdDebug() << "kio_msits::get() " << url.path() << endl; if ( !parseLoadAndLookup ( url, fileName ) ) return; // error() has been called by parseLoadAndLookup kdDebug() << "kio_msits::get: parseLoadAndLookup returned " << fileName << endl; if ( LCHMUrlFactory::handleFileType( url.path(), htmdata ) ) { buf = htmdata.utf8(); kdDebug() << "Using special handling for image pages: " << htmdata << endl; } else { if ( isDirectory (fileName) ) { error( KIO::ERR_IS_DIRECTORY, url.prettyURL() ); return; } if ( !ResolveObject ( fileName, &ui) ) { kdDebug() << "kio_msits::get: could not resolve filename " << fileName << endl; error( KIO::ERR_DOES_NOT_EXIST, url.prettyURL() ); return; } buf.resize( ui.length ); if ( RetrieveObject (&ui, (unsigned char*) buf.data(), 0, ui.length) == 0 ) { kdDebug() << "kio_msits::get: could not retrieve filename " << fileName << endl; error( KIO::ERR_NO_CONTENT, url.prettyURL() ); return; } } totalSize( buf.size() ); KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType( buf, fileName ); kdDebug() << "Emitting mimetype " << result->mimeType() << endl; mimeType( result->mimeType() ); data( buf ); processedSize( buf.size() ); finished(); } bool ProtocolMSITS::parseLoadAndLookup ( const KURL& url, QString& abspath ) { kdDebug() << "ProtocolMSITS::parseLoadAndLookup (const KURL&) " << url.path() << endl; int pos = url.path().find ("::"); if ( pos == -1 ) { error( KIO::ERR_MALFORMED_URL, url.prettyURL() ); return false; } QString filename = url.path().left (pos); abspath = url.path().mid (pos + 2); // skip :: // Some buggy apps add ms-its:/ to the path as well if ( abspath.startsWith( "ms-its:" ) ) abspath = abspath.mid( 7 ); kdDebug() << "ProtocolMSITS::parseLoadAndLookup: filename " << filename << ", path " << abspath << endl; if ( filename.isEmpty() ) { error( KIO::ERR_MALFORMED_URL, url.prettyURL() ); return false; } // If the file has been already loaded, nothing to do. if ( m_chmFile && filename == m_openedFile ) return true; kdDebug() << "Opening a new CHM file " << filename << endl; // First try to open a temporary file chmFile * tmpchm; if ( (tmpchm = chm_open ( QFile::encodeName (filename))) == 0 ) { error( KIO::ERR_COULD_NOT_READ, url.prettyURL() ); return false; } // Replace an existing file by a new one if ( m_chmFile ) chm_close (m_chmFile); m_chmFile = tmpchm; m_openedFile = filename; kdDebug() << "A CHM file " << filename << " has beed opened successfully" << endl; return true; } /* * Shamelessly stolen from a KDE KIO tutorial */ static void app_entry(UDSEntry& e, unsigned int uds, const QString& str) { UDSAtom a; a.m_uds = uds; a.m_str = str; e.append(a); } // appends an int with the UDS-ID uds static void app_entry(UDSEntry& e, unsigned int uds, long l) { UDSAtom a; a.m_uds = uds; a.m_long = l; e.append(a); } // internal function // fills a directory item with its name and size static void app_dir(UDSEntry& e, const QString & name) { e.clear(); app_entry(e, KIO::UDS_NAME, name); app_entry(e, KIO::UDS_FILE_TYPE, S_IFDIR); app_entry(e, KIO::UDS_SIZE, 1); } // internal function // fills a file item with its name and size static void app_file(UDSEntry& e, const QString & name, size_t size) { e.clear(); app_entry(e, KIO::UDS_NAME, name); app_entry(e, KIO::UDS_FILE_TYPE, S_IFREG); app_entry(e, KIO::UDS_SIZE, size); } void ProtocolMSITS::stat (const KURL & url) { QString fileName; chmUnitInfo ui; kdDebug() << "kio_msits::stat (const KURL& url) " << url.path() << endl; if ( !parseLoadAndLookup ( url, fileName ) ) return; // error() has been called by parseLoadAndLookup if ( !ResolveObject ( fileName, &ui ) ) { error( KIO::ERR_DOES_NOT_EXIST, url.prettyURL() ); return; } kdDebug() << "kio_msits::stat: adding an entry for " << fileName << endl; UDSEntry entry; if ( isDirectory ( fileName ) ) app_dir(entry, fileName); else app_file(entry, fileName, ui.length); statEntry (entry); finished(); } // A local CHMLIB enumerator static int chmlib_enumerator (struct chmFile *, struct chmUnitInfo *ui, void *context) { ((QValueVector *) context)->push_back (QString::fromLocal8Bit (ui->path)); return CHM_ENUMERATOR_CONTINUE; } void ProtocolMSITS::listDir (const KURL & url) { QString filepath; kdDebug() << "kio_msits::listDir (const KURL& url) " << url.path() << endl; if ( !parseLoadAndLookup ( url, filepath ) ) return; // error() has been called by parseLoadAndLookup filepath += "/"; if ( !isDirectory (filepath) ) { error(KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path()); return; } kdDebug() << "kio_msits::listDir: enumerating directory " << filepath << endl; QValueVector listing; if ( chm_enumerate_dir ( m_chmFile, filepath.local8Bit(), CHM_ENUMERATE_NORMAL | CHM_ENUMERATE_FILES | CHM_ENUMERATE_DIRS, chmlib_enumerator, &listing ) != 1 ) { error(KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path()); return; } UDSEntry entry; unsigned int striplength = filepath.length(); for ( unsigned int i = 0; i < listing.size(); i++ ) { // Strip the direcroty name QString ename = listing[i].mid (striplength); if ( isDirectory ( ename ) ) app_dir(entry, ename); else app_file(entry, ename, 0); listEntry(entry, false); } listEntry(entry, true); finished(); }