diff options
Diffstat (limited to 'parts/documentation/protocols/chm/chm.cpp')
-rw-r--r-- | parts/documentation/protocols/chm/chm.cpp | 362 |
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); +} |