38#include <QtCore/QFileInfo>
39#include <QtCore/QFile>
40#include <QtCore/QRegExp>
41#include <QtCore/QTextCodec>
42#include <QtGui/QTextDocument>
45#ifdef HAVE_SYS_TYPES_H
46# include <sys/types.h>
61#include <libxslt/xsltutils.h>
62#include <libxslt/transform.h>
66QString HelpProtocol::langLookup(
const QString &fname)
75 langs.removeAll(
"C" );
79 for (QStringList::Iterator it = langs.begin(); it != langs.end(); ++it)
84 int ldCount = localDoc.count();
85 for (
int id=0;
id < ldCount;
id++)
87 QStringList::ConstIterator lang;
88 for (lang = langs.constBegin(); lang != langs.constEnd(); ++lang)
89 search.append(QString(
"%1%2/%3").arg(localDoc[
id], *lang, fname));
93 for (QStringList::ConstIterator it = search.constBegin(); it != search.constEnd(); ++it)
95 kDebug( 7119 ) <<
"Looking for help in: " << *it;
98 if (info.exists() && info.isFile() && info.isReadable())
101 if ( ( *it ).endsWith( QLatin1String(
".html") ) )
103 QString file = (*it).left((*it).lastIndexOf(
'/')) +
"/index.docbook";
104 kDebug( 7119 ) <<
"Looking for help in: " << file;
106 if (info.exists() && info.isFile() && info.isReadable())
116QString HelpProtocol::lookupFile(
const QString &fname,
117 const QString &query,
bool &redirect)
121 const QString path = fname;
123 QString result = langLookup(path);
124 if (result.isEmpty())
126 result = langLookup(path+
"/index.html");
127 if (!result.isEmpty())
129 KUrl red(
"help:/" );
130 red.setPath( path +
"/index.html" );
131 red.setQuery( query );
133 kDebug( 7119 ) <<
"redirect to " << red.url();
138 const QString documentationNotFound =
"khelpcenter/documentationnotfound/index.html";
139 if (!langLookup(documentationNotFound).isEmpty())
143 red.
setPath(documentationNotFound);
150 unicodeError(
i18n(
"There is no documentation available for %1." , Qt::escape(path)) );
155 kDebug( 7119 ) <<
"result " << result;
161void HelpProtocol::unicodeError(
const QString &t )
164 QString encoding =
"UTF-8";
166 QString encoding = QTextCodec::codecForLocale()->name();
169 "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\"></head>\n"
170 "%2</html>" ).arg( encoding, Qt::escape(t) ) ) );
177 :
SlaveBase( ghelp ?
"ghelp" :
"help", pool, app ), mGhelp( ghelp )
185 <<
"query=" << url.
query();
188 QString doc = QDir::cleanPath(url.
path());
189 if (doc.contains(
"..")) {
195 if (!doc.startsWith(
'/'))
196 doc = doc.prepend(QLatin1Char(
'/'));
198 if (doc.endsWith(
'/'))
205 doc = lookupFile(doc, url.
query(), redirect);
226 kDebug( 7119 ) <<
"target " << target.
url();
228 QString file = target.scheme() ==
"file" ? target.
toLocalFile() : target.
path();
231 if ( !file.endsWith( QLatin1String(
".xml" ) ) ) {
236 QString docbook_file = file.left(file.lastIndexOf(
'/')) +
"/index.docbook";
242 file = file +
"/index.docbook";
244 if ( !file.endsWith( QLatin1String(
".html" ) ) || !
compareTimeStamps( file, docbook_file ) ) {
256 QString xsl =
"customization/kde-nochunk.xsl";
259 kDebug( 7119 ) <<
"parsed " << mParsed.length();
261 if (mParsed.isEmpty()) {
262 unicodeError(
i18n(
"The requested help file could not be parsed:<br />%1" , file ) );
264 int pos1 = mParsed.indexOf(
"charset=" );
266 int pos2 = mParsed.indexOf(
'"', pos1 );
268 mParsed.replace( pos1, pos2 - pos1,
"charset=UTF-8" );
271 data( mParsed.toUtf8() );
275 kDebug( 7119 ) <<
"look for cache for " << file;
279 kDebug( 7119 ) <<
"cached parsed " << mParsed.length();
281 if ( mParsed.isEmpty() ) {
283 if ( !mParsed.isEmpty() ) {
291 QString cache =
'/' + fi.absolutePath().remove(
KStandardDirs::installPath(
"html"),Qt::CaseInsensitive).replace(
'/',
'_') +
'_' + fi.baseName() +
'.';
293 QString cache = file.left( file.length() - 7 );
301 kDebug( 7119 ) <<
"parsed " << mParsed.length();
303 if (mParsed.isEmpty()) {
304 unicodeError(
i18n(
"The requested help file could not be parsed:<br />%1" , file ) );
306 QString query = url.
query(), anchor;
309 if (!query.isEmpty())
310 if (query.startsWith(QLatin1String(
"?anchor="))) {
311 anchor = query.mid(8).toLower();
324 kDebug( 7119 ) <<
"anchor: " << anchor;
326 if ( !anchor.isEmpty() )
330 index = mParsed.indexOf( QRegExp(
"<a name=" ), index);
332 kDebug( 7119 ) <<
"no anchor\n";
336 if ( mParsed.mid( index, 11 + anchor.length() ).toLower() ==
337 QString(
"<a name=\"%1\">" ).arg( anchor ) )
339 index = mParsed.lastIndexOf(
"<FILENAME filename=", index ) +
340 strlen(
"<FILENAME filename=\"" );
341 QString filename=mParsed.mid( index, 2000 );
342 filename = filename.left( filename.indexOf(
'\"' ) );
343 QString path = target.
path();
344 path = path.left( path.lastIndexOf(
'/' ) + 1) + filename;
346 kDebug( 7119 ) <<
"anchor found in " << target.
url();
359void HelpProtocol::emitFile(
const KUrl& url )
363 QString filename = url.
path().mid(url.
path().lastIndexOf(
'/') + 1);
365 int index = mParsed.indexOf(QString(
"<FILENAME filename=\"%1\"").arg(filename));
367 if ( filename ==
"index.html" ) {
372 unicodeError(
i18n(
"Could not find filename %1 in %2.", filename, url.
url() ) );
376 QString filedata =
splitOut(mParsed, index);
380 data( QByteArray() );
391#define MAX_IPC_SIZE (1024*32)
393void HelpProtocol::get_file(
const KUrl& url )
395 kDebug( 7119 ) <<
"get_file " << url.
url();
403 if ( !f.open(QIODevice::ReadOnly) ) {
407 int processed_size = 0;
415 qint64 n = f.read(array.data(),array.size());
430 data( QByteArray() );
436 QByteArray _path( QFile::encodeName(url.
path()));
437 KDE_struct_stat buff;
438 if ( KDE_stat( _path.data(), &buff ) == -1 ) {
439 if ( errno == EACCES )
446 if ( S_ISDIR( buff.st_mode ) ) {
450 if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
455 int fd = KDE_open( _path.data(), O_RDONLY);
462 int processed_size = 0;
481 array = array.fromRawData(buffer, n);
483 array = array.fromRawData(buffer, n);
489 data( QByteArray() );
virtual void get(const KUrl &url)
HelpProtocol(bool ghelp, const QByteArray &pool, const QByteArray &app)
virtual void mimetype(const KUrl &url)
void mimeType(const QString &_type)
void infoMessage(const QString &msg)
void processedSize(KIO::filesize_t _bytes)
void redirection(const KUrl &_url)
void error(int _errid, const QString &_text)
void data(const QByteArray &data)
void totalSize(KIO::filesize_t _bytes)
virtual void read(KIO::filesize_t size)
QStringList languageList() const
static bool exists(const QString &fullPath)
static QString installPath(const char *type)
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
static QString locateLocal(const char *type, const QString &filename, bool createDir, const KComponentData &cData=KGlobal::mainComponent())
QStringList resourceDirs(const char *type) const
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
void setProtocol(const QString &proto)
void setPath(const QString &path)
void setQuery(const QString &query)
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
void setHTMLRef(const QString &_ref)
QString i18n(const char *text)
ERR_CANNOT_OPEN_FOR_READING
void replaceCharsetHeader(QString &output)
QString splitOut(const QString &parsed, int index)
QByteArray fromUnicode(const QString &data)
QString transform(const QString &pat, const QString &tss, const QVector< const char * > ¶ms)
bool saveToCache(const QString &contents, const QString &filename)
QString lookForCache(const QString &filename)
bool compareTimeStamps(const QString &older, const QString &newer)
Compares two files and returns true if.