summaryrefslogtreecommitdiffstats
path: root/lib/kio-msits/msits.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kio-msits/msits.cpp')
-rwxr-xr-xlib/kio-msits/msits.cpp320
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();
+}