summaryrefslogtreecommitdiffstats
path: root/lib/tdeio-msits
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tdeio-msits')
-rw-r--r--lib/tdeio-msits/Makefile.am14
-rw-r--r--lib/tdeio-msits/kchmviewer.desktop11
-rwxr-xr-xlib/tdeio-msits/msits.cpp320
-rwxr-xr-xlib/tdeio-msits/msits.h79
-rwxr-xr-xlib/tdeio-msits/msits.protocol24
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, [email protected] *
+ * 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, [email protected] *
+ * 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