diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 14:20:53 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 14:20:53 -0600 |
commit | e3379a9953ab5532065dbe90bdb5a5fe14565641 (patch) | |
tree | 744fa731d7349b3ac60ad82f2f56605a19b86b0c /kdoctools/tdeio_help.cpp | |
parent | a3e01ba75c1f4886f3d2f2abeeb2715f39957974 (diff) | |
download | tdelibs-e3379a9953ab5532065dbe90bdb5a5fe14565641.tar.gz tdelibs-e3379a9953ab5532065dbe90bdb5a5fe14565641.zip |
Rename additional kioslave libraries
Diffstat (limited to 'kdoctools/tdeio_help.cpp')
-rw-r--r-- | kdoctools/tdeio_help.cpp | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/kdoctools/tdeio_help.cpp b/kdoctools/tdeio_help.cpp new file mode 100644 index 000000000..d6d5f285a --- /dev/null +++ b/kdoctools/tdeio_help.cpp @@ -0,0 +1,404 @@ +#include <config.h> + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif + +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_STDIO_H +# include <stdio.h> +#endif +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include <tqvaluelist.h> +#include <tqfileinfo.h> +#include <tqfile.h> +#include <tqtextstream.h> +#include <tqregexp.h> +#include <tqtextcodec.h> + +#include <kdebug.h> +#include <kurl.h> +#include <kglobal.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kinstance.h> + +#include "tdeio_help.h" +#include <libxslt/xsltutils.h> +#include <libxslt/transform.h> +#include "xslt.h" + +using namespace TDEIO; + +TQString HelpProtocol::langLookup(const TQString& fname) +{ + TQStringList search; + + // assemble the local search paths + const TQStringList localDoc = TDEGlobal::dirs()->resourceDirs("html") + TDEGlobal::dirs()->resourceDirs("html-bundle"); + + TQStringList langs = TDEGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( "C" ); + + // this is kind of compat hack as we install our docs in en/ but the + // default language is en_US + for (TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if ( *it == "en_US" ) + *it = "en"; + + // look up the different languages + int ldCount = localDoc.count(); + for (int id=0; id < ldCount; id++) + { + TQStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(TQString("%1%2/%3").arg(localDoc[id], *lang, fname)); + } + + // try to locate the file + TQStringList::Iterator it; + for (it = search.begin(); it != search.end(); ++it) + { + kdDebug( 7119 ) << "Looking for help in: " << *it << endl; + + TQFileInfo info(*it); + if (info.exists() && info.isFile() && info.isReadable()) + return *it; + + if ( ( *it ).right( 5 ) == ".html" ) + { + TQString file = (*it).left((*it).findRev('/')) + "/index.docbook"; + kdDebug( 7119 ) << "Looking for help in: " << file << endl; + info.setFile(file); + if (info.exists() && info.isFile() && info.isReadable()) + return *it; + } + } + + + return TQString::null; +} + + +TQString HelpProtocol::lookupFile(const TQString &fname, + const TQString &query, bool &redirect) +{ + redirect = false; + + TQString path, result; + + path = fname; + + result = langLookup(path); + if (result.isEmpty()) + { + result = langLookup(path+"/index.html"); + if (!result.isEmpty()) + { + KURL red( "help:/" ); + red.setPath( path + "/index.html" ); + red.setQuery( query ); + redirection(red); + kdDebug( 7119 ) << "redirect to " << red.url() << endl; + redirect = true; + } + else + { + unicodeError( i18n("There is no documentation available for %1." ).arg(path) ); + finished(); + return TQString::null; + } + } else + kdDebug( 7119 ) << "result " << result << endl; + + return result; +} + + +void HelpProtocol::unicodeError( const TQString &t ) +{ + data(fromUnicode( TQString( + "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\"></head>\n" + "%2</html>" ).arg( TQTextCodec::codecForLocale()->name() ).arg( t ) ) ); +} + +HelpProtocol *slave = 0; + +HelpProtocol::HelpProtocol( bool ghelp, const TQCString &pool, const TQCString &app ) + : SlaveBase( ghelp ? "ghelp" : "help", pool, app ), mGhelp( ghelp ) +{ + slave = this; +} + +void HelpProtocol::get( const KURL& url ) +{ + kdDebug( 7119 ) << "get: path=" << url.path() + << " query=" << url.query() << endl; + + bool redirect; + TQString doc; + doc = url.path(); + + if ( !mGhelp ) { + if (doc.at(0) != '/') + doc = doc.prepend('/'); + + if (doc.at(doc.length() - 1) == '/') + doc += "index.html"; + } + + infoMessage(i18n("Looking up correct file")); + + if ( !mGhelp ) { + doc = lookupFile(doc, url.query(), redirect); + + if (redirect) + { + finished(); + return; + } + } + + if (doc.isEmpty()) + { + error( TDEIO::ERR_DOES_NOT_EXIST, url.url() ); + return; + } + + mimeType("text/html"); + KURL target; + target.setPath(doc); + if (url.hasHTMLRef()) + target.setHTMLRef(url.htmlRef()); + + kdDebug( 7119 ) << "target " << target.url() << endl; + + TQString file = target.path(); + + if ( mGhelp ) { + if ( file.right( 4 ) != ".xml" ) { + get_file( target ); + return; + } + } else { + TQString docbook_file = file.left(file.findRev('/')) + "/index.docbook"; + if (!KStandardDirs::exists(file)) { + file = docbook_file; + } else { + TQFileInfo fi(file); + if (fi.isDir()) { + file = file + "/index.docbook"; + } else { + if ( file.right( 5 ) != ".html" || !compareTimeStamps( file, docbook_file ) ) { + get_file( target ); + return; + } else + file = docbook_file; + } + } + } + + infoMessage(i18n("Preparing document")); + + if ( mGhelp ) { + TQString xsl = "customization/kde-nochunk.xsl"; + mParsed = transform(file, locate("dtd", xsl)); + + kdDebug( 7119 ) << "parsed " << mParsed.length() << endl; + + if (mParsed.isEmpty()) { + unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) ); + } else { + int pos1 = mParsed.find( "charset=" ); + if ( pos1 > 0 ) { + int pos2 = mParsed.find( '"', pos1 ); + if ( pos2 > 0 ) { + mParsed.replace( pos1, pos2 - pos1, "charset=UTF-8" ); + } + } + data( mParsed.utf8() ); + } + } else { + + kdDebug( 7119 ) << "look for cache for " << file << endl; + + mParsed = lookForCache( file ); + + kdDebug( 7119 ) << "cached parsed " << mParsed.length() << endl; + + if ( mParsed.isEmpty() ) { + mParsed = transform(file, locate("dtd", "customization/kde-chunk.xsl")); + if ( !mParsed.isEmpty() ) { + infoMessage( i18n( "Saving to cache" ) ); + TQString cache = file.left( file.length() - 7 ); + saveToCache( mParsed, locateLocal( "cache", + "tdeio_help" + cache + + "cache.bz2" ) ); + } + } else infoMessage( i18n( "Using cached version" ) ); + + kdDebug( 7119 ) << "parsed " << mParsed.length() << endl; + + if (mParsed.isEmpty()) { + unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) ); + } else { + TQString query = url.query(), anchor; + + // if we have a query, look if it contains an anchor + if (!query.isEmpty()) + if (query.left(8) == "?anchor=") { + anchor = query.mid(8).lower(); + + KURL redirURL(url); + + redirURL.setQuery(TQString::null); + redirURL.setHTMLRef(anchor); + redirection(redirURL); + finished(); + return; + } + if (anchor.isEmpty() && url.hasHTMLRef()) + anchor = url.htmlRef(); + + kdDebug( 7119 ) << "anchor: " << anchor << endl; + + if ( !anchor.isEmpty() ) + { + int index = 0; + while ( true ) { + index = mParsed.find( TQRegExp( "<a name=" ), index); + if ( index == -1 ) { + kdDebug( 7119 ) << "no anchor\n"; + break; // use whatever is the target, most likely index.html + } + + if ( mParsed.mid( index, 11 + anchor.length() ).lower() == + TQString( "<a name=\"%1\">" ).arg( anchor ) ) + { + index = mParsed.findRev( "<FILENAME filename=", index ) + + strlen( "<FILENAME filename=\"" ); + TQString filename=mParsed.mid( index, 2000 ); + filename = filename.left( filename.find( '\"' ) ); + TQString path = target.path(); + path = path.left( path.findRev( '/' ) + 1) + filename; + kdDebug( 7119 ) << "anchor found in " << path <<endl; + target.setPath( path ); + break; + } + index++; + } + } + emitFile( target ); + } + } + + finished(); +} + +void HelpProtocol::emitFile( const KURL& url ) +{ + infoMessage(i18n("Looking up section")); + + TQString filename = url.path().mid(url.path().findRev('/') + 1); + + int index = mParsed.find(TQString("<FILENAME filename=\"%1\"").arg(filename)); + if (index == -1) { + if ( filename == "index.html" ) { + data( fromUnicode( mParsed ) ); + return; + } + + unicodeError( i18n("Could not find filename %1 in %2.").arg(filename).arg( url.url() ) ); + return; + } + + TQString filedata = splitOut(mParsed, index); + replaceCharsetHeader( filedata ); + + data( fromUnicode( filedata ) ); + data( TQByteArray() ); +} + +void HelpProtocol::mimetype( const KURL &) +{ + mimeType("text/html"); + finished(); +} + +// Copied from tdeio_file to avoid redirects + +#define MAX_IPC_SIZE (1024*32) + +void HelpProtocol::get_file( const KURL& url ) +{ + kdDebug( 7119 ) << "get_file " << url.url() << endl; + + TQCString _path( TQFile::encodeName(url.path())); + struct stat buff; + if ( ::stat( _path.data(), &buff ) == -1 ) { + if ( errno == EACCES ) + error( TDEIO::ERR_ACCESS_DENIED, url.path() ); + else + error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); + return; + } + + if ( S_ISDIR( buff.st_mode ) ) { + error( TDEIO::ERR_IS_DIRECTORY, url.path() ); + return; + } + if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); + return; + } + + int fd = open( _path.data(), O_RDONLY); + if ( fd < 0 ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); + return; + } + + totalSize( buff.st_size ); + int processed_size = 0; + + char buffer[ MAX_IPC_SIZE ]; + TQByteArray array; + + while( 1 ) + { + int n = ::read( fd, buffer, MAX_IPC_SIZE ); + if (n == -1) + { + if (errno == EINTR) + continue; + error( TDEIO::ERR_COULD_NOT_READ, url.path()); + close(fd); + return; + } + if (n == 0) + break; // Finished + + array.setRawData(buffer, n); + data( array ); + array.resetRawData(buffer, n); + + processed_size += n; + processedSize( processed_size ); + } + + data( TQByteArray() ); + + close( fd ); + + processedSize( buff.st_size ); + + finished(); +} |