(raw) port of help slave for khelpcenter

This commit is contained in:
Ivailo Monev 2015-09-03 08:01:50 +00:00
parent 17173d33ef
commit 068efba578
10 changed files with 1093 additions and 0 deletions

View file

@ -0,0 +1,10 @@
[Protocol]
exec=kio_help
protocol=help
input=none
output=filesystem
reading=true
defaultMimetype=text/html
Icon=help-browser
Class=:local
X-DocPath=kioslave/help/index.html

View file

@ -0,0 +1,495 @@
/* This file is part of the KDE libraries
Copyright (C) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
Copyright (C) 2001 Stephan Kulow <coolo@kde.org>
Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
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 versio
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kio_help.h"
#include "xslt.h"
#include "xslt_help.h"
#include <kdebug.h>
#include <kde_file.h>
#include <kurl.h>
#include <kglobal.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kcomponentdata.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFile>
#include <QtCore/QRegExp>
#include <QtCore/QTextCodec>
#include <QtGui/QTextDocument>
#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 <libxslt/xsltutils.h>
#include <libxslt/transform.h>
using namespace KIO;
QString HelpProtocol::langLookup(const QString &fname)
{
QStringList search;
// assemble the local search paths
const QStringList localDoc = KGlobal::dirs()->resourceDirs("html");
QStringList langs = KGlobal::locale()->languageList();
langs.append( "en" );
langs.removeAll( "C" );
// this is kind of compat hack as we install our docs in en/ but the
// default language is en_US
for (QStringList::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++)
{
QStringList::ConstIterator lang;
for (lang = langs.constBegin(); lang != langs.constEnd(); ++lang)
search.append(QString("%1%2/%3").arg(localDoc[id], *lang, fname));
}
// try to locate the file
for (QStringList::ConstIterator it = search.constBegin(); it != search.constEnd(); ++it)
{
kDebug( 7119 ) << "Looking for help in: " << *it;
QFileInfo info(*it);
if (info.exists() && info.isFile() && info.isReadable())
return *it;
if ( ( *it ).endsWith( QLatin1String(".html") ) )
{
QString file = (*it).left((*it).lastIndexOf('/')) + "/index.docbook";
kDebug( 7119 ) << "Looking for help in: " << file;
info.setFile(file);
if (info.exists() && info.isFile() && info.isReadable())
return *it;
}
}
return QString();
}
QString HelpProtocol::lookupFile(const QString &fname,
const QString &query, bool &redirect)
{
redirect = false;
const QString path = fname;
QString 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);
kDebug( 7119 ) << "redirect to " << red.url();
redirect = true;
}
else
{
const QString documentationNotFound = "khelpcenter/documentationnotfound/index.html";
if (!langLookup(documentationNotFound).isEmpty())
{
KUrl red;
red.setProtocol("help");
red.setPath(documentationNotFound);
red.setQuery(query);
redirection(red);
redirect = true;
}
else
{
unicodeError( i18n("There is no documentation available for %1." , Qt::escape(path)) );
return QString();
}
}
} else
kDebug( 7119 ) << "result " << result;
return result;
}
void HelpProtocol::unicodeError( const QString &t )
{
#ifdef Q_WS_WIN
QString encoding = "UTF-8";
#else
QString encoding = QTextCodec::codecForLocale()->name();
#endif
data(fromUnicode( QString(
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\"></head>\n"
"%2</html>" ).arg( encoding, Qt::escape(t) ) ) );
}
HelpProtocol *slave = 0;
HelpProtocol::HelpProtocol( bool ghelp, const QByteArray &pool, const QByteArray &app )
: SlaveBase( ghelp ? "ghelp" : "help", pool, app ), mGhelp( ghelp )
{
slave = this;
}
void HelpProtocol::get( const KUrl& url )
{
kDebug( 7119 ) << "path=" << url.path()
<< "query=" << url.query();
bool redirect;
QString doc = QDir::cleanPath(url.path());
if (doc.contains("..")) {
error( KIO::ERR_DOES_NOT_EXIST, url.url() );
return;
}
if ( !mGhelp ) {
if (!doc.startsWith('/'))
doc = doc.prepend(QLatin1Char('/'));
if (doc.endsWith('/'))
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( KIO::ERR_DOES_NOT_EXIST, url.url() );
return;
}
mimeType("text/html");
KUrl target;
target.setPath(doc);
if (url.hasHTMLRef())
target.setHTMLRef(url.htmlRef());
kDebug( 7119 ) << "target " << target.url();
QString file = target.scheme() == "file" ? target.toLocalFile() : target.path();
if ( mGhelp ) {
if ( !file.endsWith( QLatin1String( ".xml" ) ) ) {
get_file( target );
return;
}
} else {
QString docbook_file = file.left(file.lastIndexOf('/')) + "/index.docbook";
if (!KStandardDirs::exists(file)) {
file = docbook_file;
} else {
QFileInfo fi(file);
if (fi.isDir()) {
file = file + "/index.docbook";
} else {
if ( !file.endsWith( QLatin1String( ".html" ) ) || !compareTimeStamps( file, docbook_file ) ) {
get_file( target );
return;
} else
file = docbook_file;
}
}
}
infoMessage(i18n("Preparing document"));
if ( mGhelp ) {
QString xsl = "customization/kde-nochunk.xsl";
mParsed = transform(file, KStandardDirs::locate("dtd", xsl));
kDebug( 7119 ) << "parsed " << mParsed.length();
if (mParsed.isEmpty()) {
unicodeError( i18n( "The requested help file could not be parsed:<br />%1" , file ) );
} else {
int pos1 = mParsed.indexOf( "charset=" );
if ( pos1 > 0 ) {
int pos2 = mParsed.indexOf( '"', pos1 );
if ( pos2 > 0 ) {
mParsed.replace( pos1, pos2 - pos1, "charset=UTF-8" );
}
}
data( mParsed.toUtf8() );
}
} else {
kDebug( 7119 ) << "look for cache for " << file;
mParsed = lookForCache( file );
kDebug( 7119 ) << "cached parsed " << mParsed.length();
if ( mParsed.isEmpty() ) {
mParsed = transform(file, KStandardDirs::locate("dtd", "customization/kde-chunk.xsl"));
if ( !mParsed.isEmpty() ) {
infoMessage( i18n( "Saving to cache" ) );
#ifdef Q_WS_WIN
QFileInfo fi(file);
// make sure filenames do not contain the base path, otherwise
// accessing user data from another location invalids cached files
// Accessing user data under a different path is possible
// when using usb sticks - this may affect unix/mac systems also
QString cache = '/' + fi.absolutePath().remove(KStandardDirs::installPath("html"),Qt::CaseInsensitive).replace('/','_') + '_' + fi.baseName() + '.';
#else
QString cache = file.left( file.length() - 7 );
#endif
saveToCache( mParsed, KStandardDirs::locateLocal( "cache",
"kio_help" + cache +
"cache.bz2" ) );
}
} else infoMessage( i18n( "Using cached version" ) );
kDebug( 7119 ) << "parsed " << mParsed.length();
if (mParsed.isEmpty()) {
unicodeError( i18n( "The requested help file could not be parsed:<br />%1" , file ) );
} else {
QString query = url.query(), anchor;
// if we have a query, look if it contains an anchor
if (!query.isEmpty())
if (query.startsWith(QLatin1String("?anchor="))) {
anchor = query.mid(8).toLower();
KUrl redirURL(url);
redirURL.setQuery(QString());
redirURL.setHTMLRef(anchor);
redirection(redirURL);
finished();
return;
}
if (anchor.isEmpty() && url.hasHTMLRef())
anchor = url.htmlRef();
kDebug( 7119 ) << "anchor: " << anchor;
if ( !anchor.isEmpty() )
{
int index = 0;
while ( true ) {
index = mParsed.indexOf( QRegExp( "<a name=" ), index);
if ( index == -1 ) {
kDebug( 7119 ) << "no anchor\n";
break; // use whatever is the target, most likely index.html
}
if ( mParsed.mid( index, 11 + anchor.length() ).toLower() ==
QString( "<a name=\"%1\">" ).arg( anchor ) )
{
index = mParsed.lastIndexOf( "<FILENAME filename=", index ) +
strlen( "<FILENAME filename=\"" );
QString filename=mParsed.mid( index, 2000 );
filename = filename.left( filename.indexOf( '\"' ) );
QString path = target.path();
path = path.left( path.lastIndexOf( '/' ) + 1) + filename;
target.setPath( path );
kDebug( 7119 ) << "anchor found in " << target.url();
break;
}
index++;
}
}
emitFile( target );
}
}
finished();
}
void HelpProtocol::emitFile( const KUrl& url )
{
infoMessage(i18n("Looking up section"));
QString filename = url.path().mid(url.path().lastIndexOf('/') + 1);
int index = mParsed.indexOf(QString("<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.", filename, url.url() ) );
return;
}
QString filedata = splitOut(mParsed, index);
replaceCharsetHeader( filedata );
data( fromUnicode( filedata ) );
data( QByteArray() );
}
void HelpProtocol::mimetype( const KUrl &)
{
mimeType("text/html");
finished();
}
// Copied from kio_file to avoid redirects
#define MAX_IPC_SIZE (1024*32)
void HelpProtocol::get_file( const KUrl& url )
{
kDebug( 7119 ) << "get_file " << url.url();
#ifdef Q_WS_WIN
QFile f( url.toLocalFile() );
if ( !f.exists() ) {
error( KIO::ERR_DOES_NOT_EXIST, url.url() );
return;
}
if ( !f.open(QIODevice::ReadOnly) ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
return;
}
int processed_size = 0;
totalSize( f.size() );
QByteArray array;
array.resize(MAX_IPC_SIZE);
while( 1 )
{
qint64 n = f.read(array.data(),array.size());
if (n == -1) {
error( KIO::ERR_COULD_NOT_READ, url.path());
f.close();
return;
}
if (n == 0)
break; // Finished
data( array );
processed_size += n;
processedSize( processed_size );
}
data( QByteArray() );
f.close();
processedSize( f.size() );
finished();
#else
QByteArray _path( QFile::encodeName(url.path()));
KDE_struct_stat buff;
if ( KDE_stat( _path.data(), &buff ) == -1 ) {
if ( errno == EACCES )
error( KIO::ERR_ACCESS_DENIED, url.url() );
else
error( KIO::ERR_DOES_NOT_EXIST, url.url() );
return;
}
if ( S_ISDIR( buff.st_mode ) ) {
error( KIO::ERR_IS_DIRECTORY, url.path() );
return;
}
if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
return;
}
int fd = KDE_open( _path.data(), O_RDONLY);
if ( fd < 0 ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
return;
}
totalSize( buff.st_size );
int processed_size = 0;
char buffer[ MAX_IPC_SIZE ];
QByteArray array;
while( 1 )
{
int n = ::read( fd, buffer, MAX_IPC_SIZE );
if (n == -1)
{
if (errno == EINTR)
continue;
error( KIO::ERR_COULD_NOT_READ, url.path());
::close(fd);
return;
}
if (n == 0)
break; // Finished
array = array.fromRawData(buffer, n);
data( array );
array = array.fromRawData(buffer, n);
processed_size += n;
processedSize( processed_size );
}
data( QByteArray() );
::close( fd );
processedSize( buff.st_size );
finished();
#endif
}

View file

@ -0,0 +1,62 @@
#ifndef __help_h__
#define __help_h__
/* This file is part of the KDE libraries
Copyright (C) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
Copyright (C) 2001 Stephan Kulow <coolo@kde.org>
Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <kio/global.h>
#include <kio/slavebase.h>
#include <QtCore/QString>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
class HelpProtocol : public KIO::SlaveBase
{
public:
HelpProtocol( bool ghelp, const QByteArray &pool, const QByteArray &app);
virtual ~HelpProtocol() { }
virtual void get( const KUrl& url );
virtual void mimetype( const KUrl& url );
private:
QString langLookup(const QString &fname);
void emitFile( const KUrl &url );
void get_file( const KUrl& url );
QString lookupFile(const QString &fname, const QString &query,
bool &redirect);
void unicodeError( const QString &t );
QString mParsed;
bool mGhelp;
};
#endif

View file

@ -0,0 +1,65 @@
#ifdef _WIN32
#define LIBXML_DLL_IMPORT __declspec(dllimport)
#else
extern "C" int xmlLoadExtDtdDefaultValue;
#endif
#include "kio_help.h"
#include "xslt.h"
#include <kstandarddirs.h>
#include <kcomponentdata.h>
#include <kdebug.h>
#include <QtCore/QString>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <libxml/xmlversion.h>
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlIO.h>
#include <libxml/parserInternals.h>
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libexslt/exslt.h>
extern "C"
{
KDE_EXPORT int kdemain( int argc, char **argv )
{
Q_ASSERT(!KGlobal::hasMainComponent()); // kdeinit is messed up if this is the case.
KComponentData componentData( "kio_help", "kio_help4" );
fillInstance(componentData);
(void)componentData.config(); // we need this one to make sure system globals are read
kDebug(7101) << "Starting " << getpid();
if (argc != 4)
{
fprintf(stderr, "Usage: kio_help protocol domain-socket1 domain-socket2\n");
exit(-1);
}
LIBXML_TEST_VERSION
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
exsltRegisterAll();
HelpProtocol slave(false, argv[2], argv[3]);
slave.dispatchLoop();
kDebug(7101) << "Done";
return 0;
}
}

236
khelpcenter/slave/xslt.cpp Normal file
View file

@ -0,0 +1,236 @@
#include "xslt.h"
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxml/xmlIO.h>
#include <libxml/parserInternals.h>
#include <libxml/catalog.h>
#include <QtCore/QDate>
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QtCore/QTextCodec>
#include <klocale.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#define INFO( x )
int writeToQString(void * context, const char * buffer, int len)
{
QString *t = (QString*)context;
*t += QString::fromUtf8(buffer, len);
return len;
}
int closeQString(void * context) {
QString *t = (QString*)context;
*t += '\n';
return 0;
}
QString transform( const QString &pat, const QString& tss,
const QVector<const char *> &params )
{
QString parsed;
INFO(i18n("Parsing stylesheet"));
xsltStylesheetPtr style_sheet =
xsltParseStylesheetFile((const xmlChar *)QFile::encodeName(tss).constData());
if ( !style_sheet ) {
return parsed;
}
if (style_sheet->indent == 1)
xmlIndentTreeOutput = 1;
else
xmlIndentTreeOutput = 0;
INFO(i18n("Parsing document"));
xmlParserCtxtPtr pctxt;
pctxt = xmlNewParserCtxt();
if ( pctxt == NULL ) {
return parsed;
}
xmlDocPtr doc = xmlCtxtReadFile(pctxt, QFile::encodeName(pat), NULL,
XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_NONET);
/* Check both the returned doc (for parsing errors) and the context
(for validation errors) */
if (doc == NULL) {
return parsed;
} else {
if (pctxt->valid == 0) {
xmlFreeDoc(doc);
return parsed;
}
}
xsltTransformContextPtr ctxt;
ctxt = xsltNewTransformContext(style_sheet, doc);
if (ctxt == NULL)
return parsed;
INFO(i18n("Applying stylesheet"));
QVector<const char *> p = params;
p.append( NULL );
xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, const_cast<const char **>(&p[0]));
xmlFreeDoc(doc);
if (res != NULL) {
xmlOutputBufferPtr outp = xmlOutputBufferCreateIO(writeToQString, (xmlOutputCloseCallback)closeQString, &parsed, 0);
outp->written = 0;
INFO(i18n("Writing document"));
xsltSaveResultTo ( outp, res, style_sheet );
xmlOutputBufferFlush(outp);
xmlFreeDoc(res);
}
xsltFreeStylesheet(style_sheet);
if (parsed.isEmpty())
parsed = ' '; // avoid error message
return parsed;
}
/*
xmlParserInputPtr meinExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt) {
xmlParserInputPtr ret = NULL;
// fprintf(stderr, "loading %s %s %s\n", URL, ID, ctxt->directory);
if (URL == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt,
"failed to load external entity \"%s\"\n", ID);
return(NULL);
}
if (!qstrcmp(ID, "-//OASIS//DTD DocBook XML V4.1.2//EN"))
URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
if (!qstrcmp(ID, "-//OASIS//DTD XML DocBook V4.1.2//EN"))
URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
QString file;
if (KStandardDirs::exists( QDir::currentPath() + "/" + URL ) )
file = QDir::currentPath() + "/" + URL;
else
file = locate("dtd", URL);
ret = xmlNewInputFromFile(ctxt, file.toLatin1().constData());
if (ret == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt,
"failed to load external entity \"%s\"\n", URL);
}
return(ret);
}
*/
QString splitOut(const QString &parsed, int index)
{
int start_index = index + 1;
while (parsed.at(start_index - 1) != '>') start_index++;
int inside = 0;
QString filedata;
while (true) {
int endindex = parsed.indexOf("</FILENAME>", index);
int startindex = parsed.indexOf("<FILENAME ", index) + 1;
// kDebug() << "FILENAME " << startindex << " " << endindex << " " << inside << " " << parsed.mid(startindex + 18, 15)<< " " << parsed.length();
if (startindex > 0) {
if (startindex < endindex) {
// kDebug() << "finding another";
index = startindex + 8;
inside++;
} else {
index = endindex + 8;
inside--;
}
} else {
inside--;
index = endindex + 1;
}
if (inside == 0) {
filedata = parsed.mid(start_index, endindex - start_index);
break;
}
}
index = filedata.indexOf("<FILENAME ");
if (index > 0) {
int endindex = filedata.lastIndexOf("</FILENAME>");
while (filedata.at(endindex) != '>') endindex++;
endindex++;
filedata = filedata.left(index) + filedata.mid(endindex);
}
// filedata.replace(QRegExp(">"), "\n>");
return filedata;
}
QByteArray fromUnicode( const QString &data )
{
QTextCodec *locale = QTextCodec::codecForLocale();
QByteArray result;
char buffer[30000];
uint buffer_len = 0;
uint len = 0;
int offset = 0;
const int part_len = 5000;
QString part;
while ( offset < data.length() )
{
part = data.mid( offset, part_len );
QByteArray test = locale->fromUnicode( part );
if ( locale->toUnicode( test ) == part ) {
result += test;
offset += part_len;
continue;
}
len = part.length();
buffer_len = 0;
for ( uint i = 0; i < len; i++ ) {
QByteArray test = locale->fromUnicode( part.mid( i, 1 ) );
if ( locale->toUnicode( test ) == part.mid( i, 1 ) ) {
if (buffer_len + test.length() + 1 > sizeof(buffer))
break;
strcpy( buffer + buffer_len, test.data() );
buffer_len += test.length();
} else {
QString res;
res.sprintf( "&#%d;", part.at( i ).unicode() );
test = locale->fromUnicode( res );
if (buffer_len + test.length() + 1 > sizeof(buffer))
break;
strcpy( buffer + buffer_len, test.data() );
buffer_len += test.length();
}
}
result += QByteArray( buffer, buffer_len + 1);
offset += part_len;
}
return result;
}
void replaceCharsetHeader( QString &output )
{
QString name;
name = QTextCodec::codecForLocale()->name();
name.replace( QString( "ISO " ), "iso-" );
output.replace( QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ),
QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\">" ).arg( name ) );
}

24
khelpcenter/slave/xslt.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef _MEIN_XSLT_H_
#define _MEIN_XSLT_H_
#include <libxml/parser.h>
#include <QtCore/QString>
#include <QtCore/QVector>
class QByteArray;
class QIODevice;
class KComponentData;
QString transform(const QString &file, const QString& stylesheet,
const QVector<const char *> &params = QVector<const char *>());
QString splitOut(const QString &parsed, int index);
void fillInstance(KComponentData &ins, const QString &srcdir = QString() );
bool saveToCache( const QString &contents, const QString &filename );
QByteArray fromUnicode( const QString &data );
void replaceCharsetHeader( QString &output );
QIODevice *getBZip2device(const QString &fileName );
extern bool warnings_exist;
extern QString *SRCDIR;
#endif

View file

@ -0,0 +1,109 @@
#include "xslt_help.h"
#include "xslt.h"
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxml/xmlIO.h>
#include <libxml/parserInternals.h>
#include <libxml/catalog.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <QtCore/QDate>
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QtCore/QTextCodec>
#include <kcomponentdata.h>
#include <klocale.h>
#include <assert.h>
#include <kfilterbase.h>
#include <kfilterdev.h>
#include <stdlib.h>
#include <stdarg.h>
#include <kcharsets.h>
#include <kurl.h>
static bool readCache( const QString &filename,
const QString &cache, QString &output)
{
kDebug( 7119 ) << filename << " " << cache;
KGlobal::dirs()->addResourceType("dtd", "data", "ksgmltools2/");
if ( !compareTimeStamps( filename, cache ) )
return false;
if ( !compareTimeStamps( KStandardDirs::locate( "dtd", "customization/kde-chunk.xsl"), cache ) )
return false;
kDebug( 7119 ) << "create filter";
QIODevice *fd = ::getBZip2device(cache);
if ( !fd )
return false;
if (!fd->open(QIODevice::ReadOnly))
{
delete fd;
QFile::remove(cache);
return false;
}
kDebug( 7119 ) << "reading";
char buffer[32000];
int n;
QByteArray text;
// Also end loop in case of error, when -1 is returned
while ( ( n = fd->read(buffer, 31900) ) > 0)
{
buffer[n] = 0;
text += buffer;
}
kDebug( 7119 ) << "read " << text.length();
fd->close();
output = QString::fromUtf8( text );
delete fd;
if (n == -1)
return false;
kDebug( 7119 ) << "finished ";
return true;
}
QString lookForCache( const QString &filename )
{
kDebug() << "lookForCache " << filename;
assert( filename.endsWith( QLatin1String(".docbook") ) );
assert( QDir::isAbsolutePath(filename));
QString cache = filename.left( filename.length() - 7 );
QString output;
if ( readCache( filename, cache + "cache.bz2", output) )
return output;
#ifdef Q_WS_WIN
QFileInfo fi(filename);
// make sure filenames do not contain the base path, otherwise
// accessing user data from another location invalids cached files.
// Accessing user data under a different path is possible
// when using usb sticks - this may affect unix/mac systems also
cache = '/' + fi.absolutePath().remove(KStandardDirs::installPath("html"),Qt::CaseInsensitive).replace('/','_') + '_' + fi.baseName() + '.';
#endif
if ( readCache( filename,
KStandardDirs::locateLocal( "cache",
"kio_help" + cache +
"cache.bz2" ), output ) )
return output;
return QString();
}
bool compareTimeStamps( const QString &older, const QString &newer )
{
QFileInfo _older( older );
QFileInfo _newer( newer );
assert( _older.exists() );
if ( !_newer.exists() )
return false;
return ( _newer.lastModified() > _older.lastModified() );
}

View file

@ -0,0 +1,14 @@
#ifndef _MEIN_XSLT_HELP_H_
#define _MEIN_XSLT_HELP_H_
#include <QtCore/QString>
QString lookForCache( const QString &filename );
/**
* Compares two files and returns true if @param newer exists and is newer than
* @param older
**/
bool compareTimeStamps( const QString &older, const QString &newer );
#endif

View file

@ -0,0 +1,63 @@
#include "xslt.h"
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxml/xmlIO.h>
#include <libxml/parserInternals.h>
#include <libxml/catalog.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <QtCore/QDate>
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <kcomponentdata.h>
#include <klocale.h>
#include <assert.h>
#include <kfilterbase.h>
#include <kfilterdev.h>
#include <QtCore/QTextCodec>
#include <stdlib.h>
#include <stdarg.h>
#include <kcharsets.h>
#include <kurl.h>
void fillInstance(KComponentData &ins, const QString &srcdir)
{
QByteArray catalogs;
if ( srcdir.isEmpty() ) {
catalogs += KUrl::fromLocalFile( ins.dirs()->findResource("data", "ksgmltools2/customization/catalog.xml") ).toEncoded();
ins.dirs()->addResourceType("dtd", "data", "ksgmltools2/");
} else {
catalogs += KUrl::fromLocalFile( srcdir +"/customization/catalog.xml" ).toEncoded();
ins.dirs()->addResourceDir("dtd", srcdir);
}
setenv( "XML_CATALOG_FILES", catalogs.constData(), 1 );
xmlInitializeCatalog();
}
QIODevice *getBZip2device(const QString &fileName )
{
return KFilterDev::deviceForFile(fileName);
}
bool saveToCache( const QString &contents, const QString &filename )
{
QIODevice *fd = ::getBZip2device(filename);
if ( !fd )
return false;
if (!fd->open(QIODevice::WriteOnly))
{
delete fd;
return false;
}
fd->write( contents.toUtf8() );
fd->close();
delete fd;
return true;
}

View file

@ -0,0 +1,15 @@
#ifndef _MEIN_XSLT_KDE_H_
#define _MEIN_XSLT_KDE_H_
#include <QtCore/QString>
#include <QtCore/QVector>
class QByteArray;
class QIODevice;
class KComponentData;
void fillInstance(KComponentData &ins, const QString &srcdir = QString() );
bool saveToCache( const QString &contents, const QString &filename );
QIODevice *getBZip2device(const QString &fileName );
#endif