diff options
Diffstat (limited to 'lib/tdeio-msits')
-rw-r--r-- | lib/tdeio-msits/Makefile.am | 14 | ||||
-rw-r--r-- | lib/tdeio-msits/kchmviewer.desktop | 11 | ||||
-rwxr-xr-x | lib/tdeio-msits/msits.cpp | 320 | ||||
-rwxr-xr-x | lib/tdeio-msits/msits.h | 79 | ||||
-rwxr-xr-x | lib/tdeio-msits/msits.protocol | 24 |
5 files changed, 448 insertions, 0 deletions
diff --git a/lib/tdeio-msits/Makefile.am b/lib/tdeio-msits/Makefile.am new file mode 100644 index 0000000..37e1b64 --- /dev/null +++ b/lib/tdeio-msits/Makefile.am @@ -0,0 +1,14 @@ +METASOURCES = AUTO +INCLUDES = $(QT_INCLUDES) $(CHM_INCLUDES) $(KDE_INCLUDES) $(LIBCHMFILE_INCLUDES) + +kde_module_LTLIBRARIES = tdeio_msits.la + +tdeio_msits_la_SOURCES = msits.cpp +tdeio_msits_la_LIBADD = -ltdeio $(CHM_LIBS) +tdeio_msits_la_LDFLAGS = -module -avoid-version $(KDE_LDFLAGS) $(LIB_QT) $(LIB_TDEIO) $(LIB_TDECORE) $(KDE_PLUGIN) $(QT_LDFLAGS) + +protocol_DATA = msits.protocol +protocoldir = $(kde_servicesdir) + +# Put it here to avoid creating another directory +kde_apps_DATA = kchmviewer.desktop diff --git a/lib/tdeio-msits/kchmviewer.desktop b/lib/tdeio-msits/kchmviewer.desktop new file mode 100644 index 0000000..31558d8 --- /dev/null +++ b/lib/tdeio-msits/kchmviewer.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Categories=Qt;TDE;Utility; +Encoding=UTF-8 +Type=Application +Exec=kchmviewer %U +Icon=kchmviewer +Terminal=0 +Name=KchmViewer +GenericName=CHM (MS-Help) Viewer +Comment=A viewer for CHM (MS-Help) files +MimeType=application/chm diff --git a/lib/tdeio-msits/msits.cpp b/lib/tdeio-msits/msits.cpp new file mode 100755 index 0000000..28d2821 --- /dev/null +++ b/lib/tdeio-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 <tdeapplication.h> +#include <kdebug.h> +#include <kinstance.h> +#include <kurl.h> +#include <kmimemagic.h> + +#include <tqfile.h> +#include <tqbitarray.h> +#include <tqvaluevector.h> + +#include "msits.h" +#include "libchmurlfactory.h" + +using namespace TDEIO; + +extern "C" +{ + int kdemain( int argc, char **argv ) + { + kdDebug() << "*** tdeio_msits Init" << endl; + + TDEInstance instance( "tdeio_msits" ); + + if ( argc != 4 ) + { + kdDebug() << "Usage: tdeio_msits protocol domain-socket1 domain-socket2" << endl; + exit (-1); + } + + ProtocolMSITS slave ( argv[2], argv[3] ); + slave.dispatchLoop(); + + kdDebug() << "*** tdeio_msits Done" << endl; + return 0; + } +} + +ProtocolMSITS::ProtocolMSITS (const TQCString &pool_socket, const TQCString &app_socket) + : SlaveBase ("tdeio_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 TQString & filename ) +{ + return filename[filename.length() - 1] == '/'; +} + + +void ProtocolMSITS::get( const KURL& url ) +{ + TQString htmdata, fileName; + chmUnitInfo ui; + TQByteArray buf; + + kdDebug() << "tdeio_msits::get() " << url.path() << endl; + + if ( !parseLoadAndLookup ( url, fileName ) ) + return; // error() has been called by parseLoadAndLookup + + kdDebug() << "tdeio_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( TDEIO::ERR_IS_DIRECTORY, url.prettyURL() ); + return; + } + + if ( !ResolveObject ( fileName, &ui) ) + { + kdDebug() << "tdeio_msits::get: could not resolve filename " << fileName << endl; + error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() ); + return; + } + + buf.resize( ui.length ); + + if ( RetrieveObject (&ui, (unsigned char*) buf.data(), 0, ui.length) == 0 ) + { + kdDebug() << "tdeio_msits::get: could not retrieve filename " << fileName << endl; + error( TDEIO::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, TQString& abspath ) +{ + kdDebug() << "ProtocolMSITS::parseLoadAndLookup (const KURL&) " << url.path() << endl; + + int pos = url.path().find ("::"); + + if ( pos == -1 ) + { + error( TDEIO::ERR_MALFORMED_URL, url.prettyURL() ); + return false; + } + + TQString 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( TDEIO::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 ( TQFile::encodeName (filename))) == 0 ) + { + error( TDEIO::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 TDEIO tutorial + */ +static void app_entry(UDSEntry& e, unsigned int uds, const TQString& 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 TQString & name) +{ + e.clear(); + app_entry(e, TDEIO::UDS_NAME, name); + app_entry(e, TDEIO::UDS_FILE_TYPE, S_IFDIR); + app_entry(e, TDEIO::UDS_SIZE, 1); +} + +// internal function +// fills a file item with its name and size +static void app_file(UDSEntry& e, const TQString & name, size_t size) +{ + e.clear(); + app_entry(e, TDEIO::UDS_NAME, name); + app_entry(e, TDEIO::UDS_FILE_TYPE, S_IFREG); + app_entry(e, TDEIO::UDS_SIZE, size); +} + +void ProtocolMSITS::stat (const KURL & url) +{ + TQString fileName; + chmUnitInfo ui; + + kdDebug() << "tdeio_msits::stat (const KURL& url) " << url.path() << endl; + + if ( !parseLoadAndLookup ( url, fileName ) ) + return; // error() has been called by parseLoadAndLookup + + if ( !ResolveObject ( fileName, &ui ) ) + { + error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() ); + return; + } + + kdDebug() << "tdeio_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) +{ + ((TQValueVector<TQString> *) context)->push_back (TQString::fromLocal8Bit (ui->path)); + return CHM_ENUMERATOR_CONTINUE; +} + + +void ProtocolMSITS::listDir (const KURL & url) +{ + TQString filepath; + + kdDebug() << "tdeio_msits::listDir (const KURL& url) " << url.path() << endl; + + if ( !parseLoadAndLookup ( url, filepath ) ) + return; // error() has been called by parseLoadAndLookup + + filepath += "/"; + + if ( !isDirectory (filepath) ) + { + error(TDEIO::ERR_CANNOT_ENTER_DIRECTORY, url.path()); + return; + } + + kdDebug() << "tdeio_msits::listDir: enumerating directory " << filepath << endl; + + TQValueVector<TQString> listing; + + if ( chm_enumerate_dir ( m_chmFile, + filepath.local8Bit(), + CHM_ENUMERATE_NORMAL | CHM_ENUMERATE_FILES | CHM_ENUMERATE_DIRS, + chmlib_enumerator, + &listing ) != 1 ) + { + error(TDEIO::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 + TQString 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(); +} diff --git a/lib/tdeio-msits/msits.h b/lib/tdeio-msits/msits.h new file mode 100755 index 0000000..4248908 --- /dev/null +++ b/lib/tdeio-msits/msits.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 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. * + ***************************************************************************/ + +#ifndef MSITS_H +#define MSITS_H + + +#include <tdeio/slavebase.h> +#include <kurl.h> + +#include <tqstring.h> +#include <tqcstring.h> + +#include "config.h" +#include "chm_lib.h" + + +class ProtocolMSITS : public TDEIO::SlaveBase +{ +public: + ProtocolMSITS ( const TQCString&, const TQCString& ); + virtual ~ProtocolMSITS(); + + virtual void get ( const KURL& ); + virtual void listDir (const KURL & url); + virtual void stat (const KURL & url); + +private: + // This function does next thing: + // - parses the URL to get a file name and URL inside the file; + // - loads a new CHM file, if needed; + // - returns the parsed URL inside the file; + bool parseLoadAndLookup ( const KURL&, TQString& abspath ); + + // Resolve an object inside a CHM file + inline bool ResolveObject (const TQString& fileName, chmUnitInfo *ui) + { + return m_chmFile != NULL && ::chm_resolve_object(m_chmFile, fileName.utf8(), ui) == CHM_RESOLVE_SUCCESS; + } + + // Retrieve an object from the CHM file + inline size_t RetrieveObject (const chmUnitInfo *ui, unsigned char *buffer, LONGUINT64 fileOffset, LONGINT64 bufferSize) + { +#if USE_BUILTIN_CHMLIB + return ::chm_retrieve_object(m_chmFile, ui, buffer, + fileOffset, bufferSize); +#else + return ::chm_retrieve_object(m_chmFile, const_cast<chmUnitInfo*>(ui), + buffer, fileOffset, bufferSize); +#endif + } + + // An opened file name, if presend + TQString m_openedFile; + + // a CHM structure file pointer (from chmlib) + chmFile * m_chmFile; +}; + + +#endif /* MSITS_H */ diff --git a/lib/tdeio-msits/msits.protocol b/lib/tdeio-msits/msits.protocol new file mode 100755 index 0000000..bc1d65f --- /dev/null +++ b/lib/tdeio-msits/msits.protocol @@ -0,0 +1,24 @@ +[Protocol] +exec=tdeio_msits +protocol=ms-its +input=none +output=filesystem +reading=true +listing=Name,Type,Size +defaultMimetype=text/html +Description=A tdeioslave for displaying WinHelp files +Description[da]=En tdeioslave til visning af Windows hjælpefiler +Description[de]=Ein Ein-/Ausgabemodul zur Anzeige von WinHelp-Dateien +Description[es]=Un tdeioslave para mostrar archivos WinHelp +Description[et]=WinHelp-failide kuvamise IO-moodul +Description[fr]=Un module d'entrée / sortie pour l'affichage des fichiers WinHelp +Description[hu]=KDE-protokoll WinHelp-fájlok megjelenítéséhez +Description[it]=Un tdeioslave per mostrare i file WinHelp +Description[nl]=Een tdeioslave voor het weergeven van WinHelp-bestanden +Description[pl]=tdeioslave do pokazywania plików WinHelp +Description[pt]=A 'tdeioslave' para mostrar ficheiros WinHelp +Description[pt_BR]=Um tdeioslave para exibir arquivos WinHelp +Description[ru]=Обработчик ввода-вывода для файлов WinHelp +Description[sv]=En I/O-slav för att visa WinHelp-filer +Description[xx]=xxA tdeioslave for displaying WinHelp filesxx +Icon=help |