summaryrefslogtreecommitdiffstats
path: root/parts/documentation/protocols/chm/chm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parts/documentation/protocols/chm/chm.cpp')
-rw-r--r--parts/documentation/protocols/chm/chm.cpp362
1 files changed, 362 insertions, 0 deletions
diff --git a/parts/documentation/protocols/chm/chm.cpp b/parts/documentation/protocols/chm/chm.cpp
new file mode 100644
index 00000000..1383d2b6
--- /dev/null
+++ b/parts/documentation/protocols/chm/chm.cpp
@@ -0,0 +1,362 @@
+/* This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <qcstring.h>
+#include <qbitarray.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <stack>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kinstance.h>
+#include <kglobal.h>
+#include <kurl.h>
+#include <kmimemagic.h>
+#include <ktempfile.h>
+
+#include "chm.h"
+
+
+using namespace KIO;
+
+extern "C"
+{
+ int kdemain( int argc, char **argv )
+ {
+ KInstance instance( "kio_chm" );
+
+ kdDebug() << "*** Starting kio_chm " << endl;
+
+ if (argc != 4) {
+ kdDebug() << "Usage: kio_chm protocol domain-socket1 domain-socket2" << endl;
+ exit(-1);
+ }
+
+ ChmProtocol slave(argv[2], argv[3]);
+ slave.dispatchLoop();
+
+ kdDebug() << "*** kio_chm Done" << endl;
+ return 0;
+ }
+}
+
+ChmProtocol::ChmProtocol(const QCString &pool_socket, const QCString &app_socket)
+: SlaveBase("kio_chm", pool_socket, app_socket)
+{
+ kdDebug() << "ChmProtocol::ChmProtocol()" << endl;
+}
+/* ---------------------------------------------------------------------------------- */
+
+
+ChmProtocol::~ChmProtocol()
+{
+ kdDebug() << "ChmProtocol::~ChmProtocol()" << endl;
+}
+
+
+/* ---------------------------------------------------------------------------------- */
+void ChmProtocol::get( const KURL& url )
+{
+ /** When :catalog is appended to the end, a plain-text representation of the catalog
+ * is given out where each entry consists of four lines, an integer representing the parent
+ * of the node, an integer representing a node's ID, the Title of the Node, and it's hyperlink.
+ * When :contents is appended, all contained htm- and html-files will be printed, each in a line.
+ */
+ kdDebug() << "kio_chm::get(const KURL& url) " << url.path() << endl;
+
+ bool catalog = false;
+ bool contents = false;
+ QString bigpath = url.path();
+
+ if(bigpath.endsWith(":catalog")) {
+ catalog = true;
+ int len = QString(":catalog").length();
+ bigpath.remove(bigpath.length() - len, len); ///strip :catalog from the end
+ }
+
+ if(bigpath.endsWith(":contents")) {
+ contents = true;
+ int len = QString(":contents").length();
+ bigpath.remove(bigpath.length() - len, len); ///strip :catalog from the end
+ }
+
+ QString path;
+ if ( !checkNewFile( bigpath, path ) ) {
+ error( KIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return;
+ }
+
+
+ if (m_dirMap.find(path) == m_dirMap.end()) {
+ error( KIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return;
+ }
+
+ QByteArray theData;
+
+ //init..
+ //added by lucida lucida@users.sf.net
+ QString fname = QString();
+ QString chmpath = QString();
+ KTempFile f("",".html");
+ fname = f.name();
+ QTextStream *t = f.textStream();
+ QString firstPage = QString("");
+ QString m_strIndex = QString("");
+ QString tmpstr = QString("");
+ bool m_bIndex = 0;
+
+
+ if(contents) {
+ QString output;
+ KURL u = url;
+
+ ChmDirectoryMap::Iterator it;
+ for ( it = m_dirMap.begin(); it != m_dirMap.end(); ++it) {
+ u.setPath(bigpath);
+ u.addPath(it.key());
+ output += u.prettyURL() + "\n";
+ }
+
+ data(output.local8Bit());
+ processedSize(output.length());
+ finished();
+ return;
+ }
+
+
+ //try get some page to display, if the chm missing index
+ ChmDirectoryMap::Iterator it;
+ for ( it = m_dirMap.begin(); it != m_dirMap.end(); ++it) {
+ tmpstr.sprintf("%s", it.key().latin1());
+ if ((m_strIndex == "") &&
+ (tmpstr.endsWith(".htm") || tmpstr.endsWith(".html")))
+ m_strIndex = tmpstr;
+ if ((tmpstr == "/index.htm") || (tmpstr == "/index.html")) {
+ m_strIndex = tmpstr;
+ break;
+ }
+ }
+ m_strIndex.remove(0,1);
+
+
+ if (path == "/" || catalog) {
+ bool htmlOutput = !catalog;
+ int offset = m_dirMap["/@contents"].offset;
+ int length = m_dirMap["/@contents"].length;
+ theData.setRawData(&m_contents[offset], length);
+ QString s(theData);
+ QString output;
+
+ QRegExp object("<OBJECT type=\"text/sitemap\">(.*)</OBJECT>", false);
+ object.setMinimal(true);
+
+ QRegExp nameParam("<param name=\"Name\" value=\"(.*)\">", false);
+ nameParam.setMinimal(true);
+
+ QRegExp localParam("<param name=\"Local\" value=\"(.*)\">", false);
+ localParam.setMinimal(true);
+
+ QRegExp mergeParam("<param name=\"Merge\" value=\"(.*)\">", false);
+ mergeParam.setMinimal(true);
+
+ std::stack<int> parents;
+ int counter = 1;
+ int current = 0;
+ int old = 0, pos = 0;
+ parents.push(0);
+ while ((pos = s.find(object, pos)) != -1) {
+ if(htmlOutput) output += s.mid(old, pos - old);
+ if(catalog) {
+ QRegExp ex("<UL>|</UL>", false); ex.setMinimal(true);
+ QString ms = s.mid(old, pos - old);
+ int pos = 0;
+ while( (pos = ms.find(ex, pos)) != -1) {
+ if(ms.mid(pos, 4) == "<UL>") {
+ parents.push(current);
+ } else{
+ if(parents.empty()){
+ }else{
+ current = parents.top();
+ parents.pop();
+ }
+ }
+ pos++;
+ }
+ }
+ pos += object.matchedLength();
+ old = pos;
+ QString obj = object.cap(1);
+ QString name, local;
+ if (obj.find(nameParam) != -1) {
+ name = nameParam.cap(1);
+ if (obj.find(localParam) != -1) {
+ local = localParam.cap(1);
+ //output += "<a href=\"" + local + "\">" + name + "</a>";
+ //added by lucida lucida@users.sf.net
+ if (local != "" && local != "/") {
+ if(!catalog) {
+ output += "<a target=\"browse\" href=\"" + url.url() + local + "\">" + name + "</a>";
+ }else{
+ current = counter;
+ ++counter;
+ KURL u = url;
+ u.setPath(bigpath + local);
+ QString str;
+ output += str.sprintf("%i\n%i\n", parents.top(), current);
+ output += name + "\n" + u.prettyURL() + "\n";
+ }
+ m_bIndex = 1;
+ if (firstPage == "") firstPage = url.url()+QString::fromLocal8Bit(local.latin1());
+ }
+ else
+ if(htmlOutput) output += name;
+ } else {
+ if(htmlOutput) output += name;
+ }
+ }
+ if (obj.find(mergeParam) != -1 && htmlOutput) {
+ QString link = mergeParam.cap(1);
+ QString href = link.left(link.find("::"));
+ QString path = m_chmFile.left(m_chmFile.findRev("/") + 1);
+ //output += " (<a href=\"" + path + href + "\">link</a>)";
+ m_bIndex = 1;
+ output += " (<a target=\"browse\" href=\"" + url.url() + path + href + "\">link</a>)";
+ if (firstPage == "") firstPage = url.url()+QString::fromLocal8Bit(local.latin1());
+ }
+ }
+ if(htmlOutput) output += s.mid(old);
+
+ //set left pane
+ //added by lucida, lucida@users.sf.net
+ QString lframe = QString("</HEAD><FRAMESET COLS=\"25%,*\">\n");
+ lframe += "<FRAME NAME=\"index\" src=\"file:"+ fname+"\"" + " marginwidth=\"0\"></FRAME>\n";
+ if (!m_bIndex) {
+ lframe = "</HEAD><FRAMESET>";
+ firstPage = url.url() + QString::fromLocal8Bit(m_strIndex.latin1());
+ }
+ theData.resetRawData(&m_contents[offset], length);
+ //KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType( output, path );
+ //kdDebug() << "Emitting mimetype " << result->mimeType() << endl;
+ //mimeType( result->mimeType() );
+/* QCString output1 = (QCString)(output.latin1());
+ data(output1);
+ processedSize(output1.length());*/
+
+ //construct the frame
+ //added by lucida lucida@users.sf.net
+ QString framestr = QString("<HTML><HEAD>\n");
+ framestr += lframe;
+ framestr += "<FRAME NAME=\"browse\" src=\"" + firstPage + "\">\n";
+ framestr += "</FRAME>\n";
+ framestr += "</FRAMESET></HTML>";
+ //write index file
+ //added by lucida lucida@users.sf.net
+ *t << QString::fromLocal8Bit(output.latin1()) << endl;
+
+ if(catalog) {
+ data(output.local8Bit());
+ processedSize(output.length());
+ }else{
+ data(framestr.local8Bit());
+ processedSize(framestr.length());
+ }
+ } else {
+ int offset = m_dirMap[path].offset;
+ int length = m_dirMap[path].length;
+ totalSize(length);
+ theData.setRawData(&m_contents[offset], length);
+
+ KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType( theData, path );
+ kdDebug() << "Emitting mimetype " << result->mimeType() << endl;
+ mimeType( result->mimeType() );
+ data(theData);
+ theData.resetRawData(&m_contents[offset], length);
+ processedSize(length);
+ }
+
+ finished();
+}
+
+/* --------------------------------------------------------------------------- */
+bool ChmProtocol::checkNewFile( QString fullPath, QString& path )
+{
+ //kdDebug() << "ChmProtocol::checkNewFile " << fullPath << endl;
+
+ fullPath = fullPath.replace(QRegExp("::"), "");
+
+ // Are we already looking at that file ?
+ if ( !m_chmFile.isEmpty() && fullPath.startsWith(m_chmFile) )
+ {
+ path = fullPath.mid(m_chmFile.length()).lower();
+ return true;
+ }
+
+ kdDebug() << "Need to open a new file" << endl;
+
+ m_chmFile = "";
+
+ // Find where the chm file is in the full path
+ int pos = 0;
+ QString chmFile;
+ path = "";
+
+ int len = fullPath.length();
+ if ( len != 0 && fullPath[ len - 1 ] != '/' )
+ fullPath += '/';
+
+ //kdDebug() << "the full path is " << fullPath << endl;
+ while ( (pos=fullPath.find( '/', pos+1 )) != -1 )
+ {
+ QString tryPath = fullPath.left( pos );
+ //kdDebug() << fullPath << " trying " << tryPath << endl;
+ struct stat statbuf;
+ if ( ::stat( QFile::encodeName(tryPath), &statbuf ) == 0 && !S_ISDIR(statbuf.st_mode) )
+ {
+ chmFile = tryPath;
+ path = fullPath.mid( pos ).lower();
+ kdDebug() << "fullPath=" << fullPath << " path=" << path << endl;
+ len = path.length();
+ if ( len > 2 )
+ {
+ if ( path[ len - 1 ] == '/' )
+ path.truncate( len - 1 );
+ }
+ else
+ {
+ path = QString::fromLatin1("/");
+ }
+ kdDebug() << "Found. chmFile=" << chmFile << " path=" << path << endl;
+ break;
+ }
+ }
+ if ( chmFile.isEmpty() )
+ {
+ kdDebug() << "ChmProtocol::checkNewFile: not found" << endl;
+ return false;
+ }
+
+ m_chmFile = chmFile;
+
+ // Open new file
+ //kdDebug() << "Opening Chm file on " << chmFile << endl;
+ return m_chm.read(chmFile, m_dirMap, m_contents);
+}