diff options
Diffstat (limited to 'lib/kio-msits/msits.cpp')
-rwxr-xr-x | lib/kio-msits/msits.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/lib/kio-msits/msits.cpp b/lib/kio-msits/msits.cpp new file mode 100755 index 0000000..cf7cf27 --- /dev/null +++ b/lib/kio-msits/msits.cpp @@ -0,0 +1,320 @@ +/*************************************************************************** + * 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 <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kinstance.h> +#include <kurl.h> +#include <kmimemagic.h> + +#include <qfile.h> +#include <qbitarray.h> +#include <qvaluevector.h> + +#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<QString> *) 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<QString> 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(); +} |