diff options
| author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 | 
|---|---|---|
| committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 | 
| commit | 114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch) | |
| tree | acaf47eb0fa12142d3896416a69e74cbf5a72242 /parts/documentation/protocols/chm/chm.cpp | |
| download | tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip | |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
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); +} | 
