19#include <tqvaluelist.h> 
   20#include <tqfileinfo.h> 
   22#include <tqtextstream.h> 
   24#include <tqtextcodec.h> 
   30#include <tdestandarddirs.h> 
   31#include <tdeinstance.h> 
   33#include "tdeio_help.h" 
   34#include <libxslt/xsltutils.h> 
   35#include <libxslt/transform.h> 
   40TQString HelpProtocol::langLookup(
const TQString &fname)
 
   45    const TQStringList localDoc = TDEGlobal::dirs()->resourceDirs(
"html") + TDEGlobal::dirs()->resourceDirs(
"html-bundle");
 
   47    TQStringList langs = TDEGlobal::locale()->languageList();
 
   53    for (TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it)
 
   58    int ldCount = localDoc.count();
 
   59    for (
int id=0; 
id < ldCount; 
id++)
 
   61        TQStringList::ConstIterator lang;
 
   62        for (lang = langs.begin(); lang != langs.end(); ++lang)
 
   63            search.append(TQString(
"%1%2/%3").arg(localDoc[
id], *lang, fname));
 
   67    TQStringList::Iterator it;
 
   68    for (it = search.begin(); it != search.end(); ++it)
 
   70        kdDebug( 7119 ) << 
"Looking for help in: " << *it << endl;
 
   73        if (info.exists() && info.isFile() && info.isReadable())
 
   76        if ( ( *it ).right( 5 ) == 
".html" )
 
   78            TQString file = (*it).left((*it).findRev(
'/')) + 
"/index.docbook";
 
   79            kdDebug( 7119 ) << 
"Looking for help in: " << file << endl;
 
   81            if (info.exists() && info.isFile() && info.isReadable())
 
   87    return TQString::null;
 
   91TQString HelpProtocol::lookupFile(
const TQString &fname, 
const TQString &query, 
bool &redirect)
 
   94    TQString result = langLookup(fname);
 
   97        result = langLookup(fname+
"/index.html");
 
   98        if (!result.isEmpty())
 
  101            red.setPath( fname+
"/index.html" );
 
  102            red.setQuery( query );
 
  104            kdDebug( 7119 ) << 
"redirect to " << red.url() << endl;
 
  109            const TQString helpNotFound(
"khelpcenter/helpnotfound/index.html");
 
  110            result = langLookup(helpNotFound);
 
  111            if (!result.isEmpty())
 
  114                red.setPath(helpNotFound);
 
  117                kdDebug( 7119 ) << 
"redirect to " << red.url() << endl;
 
  122                unicodeError(i18n(
"Sorry, there is no documentation available at all for %1." ).arg(fname));
 
  124                return TQString::null;
 
  128        kdDebug( 7119 ) << 
"result " << result << endl;
 
  134void HelpProtocol::unicodeError( 
const TQString &t )
 
  136   data(fromUnicode( TQString(
 
  137        "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\"></head>\n" 
  138        "%2</html>" ).arg( TQTextCodec::codecForLocale()->name() ).arg( t ) ) );
 
  141HelpProtocol *slave = 0;
 
  143HelpProtocol::HelpProtocol( 
bool ghelp, 
const TQCString &pool, 
const TQCString &app )
 
  144  : SlaveBase( ghelp ? 
"ghelp" : 
"help", pool, app ), mGhelp( ghelp )
 
  149void HelpProtocol::get( 
const KURL& url )
 
  151    kdDebug( 7119 ) << 
"get: path=" << url.path()
 
  152              << 
" query=" << url.query() << endl;
 
  159        if (doc.at(0) != 
'/')
 
  160            doc = doc.prepend(
'/');
 
  162        if (doc.at(doc.length() - 1) == 
'/')
 
  166    infoMessage(i18n(
"Looking up correct file"));
 
  169      doc = lookupFile(doc, url.query(), redirect);
 
  180        error( TDEIO::ERR_DOES_NOT_EXIST, url.url() );
 
  184    mimeType(
"text/html");
 
  187    if (url.hasHTMLRef())
 
  188        target.setHTMLRef(url.htmlRef());
 
  190    kdDebug( 7119 ) << 
"target " << target.url() << endl;
 
  192    TQString file = target.path();
 
  195      if ( file.right( 4 ) != 
".xml" ) {
 
  200        TQString docbook_file = file.left(file.findRev(
'/')) + 
"/index.docbook";
 
  201        if (!TDEStandardDirs::exists(file)) {
 
  206                file = file + 
"/index.docbook";
 
  208                if ( file.right( 5 ) != 
".html" || !compareTimeStamps( file, docbook_file ) ) {
 
  217    infoMessage(i18n(
"Preparing document"));
 
  220        TQString xsl = 
"customization/tde-nochunk.xsl";
 
  221        mParsed = transform(file, locate(
"dtd", xsl));
 
  223        kdDebug( 7119 ) << 
"parsed " << mParsed.length() << endl;
 
  225        if (mParsed.isEmpty()) {
 
  226            unicodeError( i18n( 
"The requested help file could not be parsed:<br>%1" ).arg( file ) );
 
  228            int pos1 = mParsed.find( 
"charset=" );
 
  230              int pos2 = mParsed.find( 
'"', pos1 );
 
  232                mParsed.replace( pos1, pos2 - pos1, 
"charset=UTF-8" );
 
  235            data( mParsed.utf8() );
 
  239        kdDebug( 7119 ) << 
"look for cache for " << file << endl;
 
  241        mParsed = lookForCache( file );
 
  243        kdDebug( 7119 ) << 
"cached parsed " << mParsed.length() << endl;
 
  245        if ( mParsed.isEmpty() ) {
 
  246            mParsed = transform(file, locate(
"dtd", 
"customization/tde-chunk.xsl"));
 
  247            if ( !mParsed.isEmpty() ) {
 
  248                infoMessage( i18n( 
"Saving to cache" ) );
 
  249                TQString cache = file.left( file.length() - 7 );
 
  250                saveToCache( mParsed, locateLocal( 
"cache",
 
  251                                                        "tdeio_help" + cache +
 
  254        } 
else infoMessage( i18n( 
"Using cached version" ) );
 
  256        kdDebug( 7119 ) << 
"parsed " << mParsed.length() << endl;
 
  258        if (mParsed.isEmpty()) {
 
  259            unicodeError( i18n( 
"The requested help file could not be parsed:<br>%1" ).arg( file ) );
 
  261            TQString query = url.query(), anchor;
 
  264            if (!query.isEmpty())
 
  265                if (query.left(8) == 
"?anchor=") {
 
  266                    anchor = query.mid(8).lower();
 
  270                redirURL.setQuery(TQString::null);
 
  271                redirURL.setHTMLRef(anchor);
 
  272                redirection(redirURL);
 
  276            if (anchor.isEmpty() && url.hasHTMLRef())
 
  277            anchor = url.htmlRef();
 
  279            kdDebug( 7119 ) << 
"anchor: " << anchor << endl;
 
  281            if ( !anchor.isEmpty() )
 
  285                    index = mParsed.find( TQRegExp( 
"<a name=" ), index);
 
  287                        kdDebug( 7119 ) << 
"no anchor\n";
 
  291                    if ( mParsed.mid( index, 11 + anchor.length() ).lower() ==
 
  292                         TQString( 
"<a name=\"%1\">" ).arg( anchor ) )
 
  294                        index = mParsed.findRev( 
"<FILENAME filename=", index ) +
 
  295                                 strlen( 
"<FILENAME filename=\"" );
 
  296                        TQString filename=mParsed.mid( index, 2000 );
 
  297                        filename = filename.left( filename.find( 
'\"' ) );
 
  298                        TQString path = target.path();
 
  299                        path = path.left( path.findRev( 
'/' ) + 1) + filename;
 
  300                        kdDebug( 7119 ) << 
"anchor found in " << path <<endl;
 
  301                        target.setPath( path );
 
  314void HelpProtocol::emitFile( 
const KURL& url )
 
  316    infoMessage(i18n(
"Looking up section"));
 
  318    TQString filename = url.path().mid(url.path().findRev(
'/') + 1);
 
  320    int index = mParsed.find(TQString(
"<FILENAME filename=\"%1\"").arg(filename));
 
  322        if ( filename == 
"index.html" ) {
 
  323            data( fromUnicode( mParsed ) );
 
  327        unicodeError( i18n(
"Could not find filename %1 in %2.").arg(filename).arg( url.url() ) );
 
  331    TQString filedata = splitOut(mParsed, index);
 
  332    replaceCharsetHeader( filedata );
 
  334    data( fromUnicode( filedata ) );
 
  335    data( TQByteArray() );
 
  338void HelpProtocol::mimetype( 
const KURL &)
 
  340    mimeType(
"text/html");
 
  346#define MAX_IPC_SIZE (1024*32) 
  348void HelpProtocol::get_file( 
const KURL& url )
 
  350    kdDebug( 7119 ) << 
"get_file " << url.url() << endl;
 
  352    TQCString _path( TQFile::encodeName(url.path()));
 
  354    if ( ::stat( _path.data(), &buff ) == -1 ) {
 
  355        if ( errno == EACCES )
 
  356           error( TDEIO::ERR_ACCESS_DENIED, url.path() );
 
  358           error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
 
  362    if ( S_ISDIR( buff.st_mode ) ) {
 
  363    error( TDEIO::ERR_IS_DIRECTORY, url.path() );
 
  366    if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
 
  367    error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
 
  371    int fd = open( _path.data(), O_RDONLY);
 
  373    error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
 
  377    totalSize( buff.st_size );
 
  378    int processed_size = 0;
 
  380    char buffer[ MAX_IPC_SIZE ];
 
  385       int n = ::read( fd, buffer, MAX_IPC_SIZE );
 
  390          error( TDEIO::ERR_COULD_NOT_READ, url.path());
 
  397       array.setRawData(buffer, n);
 
  399       array.resetRawData(buffer, n);
 
  402       processedSize( processed_size );
 
  405    data( TQByteArray() );
 
  409    processedSize( buff.st_size );