3 #ifdef HAVE_SYS_TYPES_H
4 # include <sys/types.h>
19 #include <tqvaluelist.h>
20 #include <tqfileinfo.h>
22 #include <tqtextstream.h>
24 #include <tqtextcodec.h>
30 #include <kstandarddirs.h>
31 #include <kinstance.h>
34 #include <libxslt/xsltutils.h>
35 #include <libxslt/transform.h>
40 TQString HelpProtocol::langLookup(
const TQString& fname)
45 const TQStringList localDoc = KGlobal::dirs()->resourceDirs(
"html") + KGlobal::dirs()->resourceDirs(
"html-bundle");
47 TQStringList langs = KGlobal::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;
91 TQString HelpProtocol::lookupFile(
const TQString &fname,
92 const TQString &query,
bool &redirect)
96 TQString path, result;
100 result = langLookup(path);
101 if (result.isEmpty())
103 result = langLookup(path+
"/index.html");
104 if (!result.isEmpty())
106 KURL red(
"help:/" );
107 red.setPath( path +
"/index.html" );
108 red.setQuery( query );
110 kdDebug( 7119 ) <<
"redirect to " << red.url() << endl;
115 unicodeError( i18n(
"There is no documentation available for %1." ).arg(path) );
117 return TQString::null;
120 kdDebug( 7119 ) <<
"result " << result << endl;
126 void HelpProtocol::unicodeError(
const TQString &t )
128 data(fromUnicode( TQString(
129 "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\"></head>\n"
130 "%2</html>" ).arg( TQTextCodec::codecForLocale()->name() ).arg( t ) ) );
133 HelpProtocol *slave = 0;
135 HelpProtocol::HelpProtocol(
bool ghelp,
const TQCString &pool,
const TQCString &app )
136 : SlaveBase( ghelp ?
"ghelp" :
"help", pool, app ), mGhelp( ghelp )
141 void HelpProtocol::get(
const KURL& url )
143 kdDebug( 7119 ) <<
"get: path=" << url.path()
144 <<
" query=" << url.query() << endl;
151 if (doc.at(0) !=
'/')
152 doc = doc.prepend(
'/');
154 if (doc.at(doc.length() - 1) ==
'/')
158 infoMessage(i18n(
"Looking up correct file"));
161 doc = lookupFile(doc, url.query(), redirect);
172 error( KIO::ERR_DOES_NOT_EXIST, url.url() );
176 mimeType(
"text/html");
179 if (url.hasHTMLRef())
180 target.setHTMLRef(url.htmlRef());
182 kdDebug( 7119 ) <<
"target " << target.url() << endl;
184 TQString file = target.path();
187 if ( file.right( 4 ) !=
".xml" ) {
192 TQString docbook_file = file.left(file.findRev(
'/')) +
"/index.docbook";
193 if (!KStandardDirs::exists(file)) {
198 file = file +
"/index.docbook";
200 if ( file.right( 5 ) !=
".html" || !compareTimeStamps( file, docbook_file ) ) {
209 infoMessage(i18n(
"Preparing document"));
212 TQString xsl =
"customization/kde-nochunk.xsl";
213 mParsed = transform(file, locate(
"dtd", xsl));
215 kdDebug( 7119 ) <<
"parsed " << mParsed.length() << endl;
217 if (mParsed.isEmpty()) {
218 unicodeError( i18n(
"The requested help file could not be parsed:<br>%1" ).arg( file ) );
220 int pos1 = mParsed.find(
"charset=" );
222 int pos2 = mParsed.find(
'"', pos1 );
224 mParsed.replace( pos1, pos2 - pos1,
"charset=UTF-8" );
227 data( mParsed.utf8() );
231 kdDebug( 7119 ) <<
"look for cache for " << file << endl;
233 mParsed = lookForCache( file );
235 kdDebug( 7119 ) <<
"cached parsed " << mParsed.length() << endl;
237 if ( mParsed.isEmpty() ) {
238 mParsed = transform(file, locate(
"dtd",
"customization/kde-chunk.xsl"));
239 if ( !mParsed.isEmpty() ) {
240 infoMessage( i18n(
"Saving to cache" ) );
241 TQString cache = file.left( file.length() - 7 );
242 saveToCache( mParsed, locateLocal(
"cache",
246 }
else infoMessage( i18n(
"Using cached version" ) );
248 kdDebug( 7119 ) <<
"parsed " << mParsed.length() << endl;
250 if (mParsed.isEmpty()) {
251 unicodeError( i18n(
"The requested help file could not be parsed:<br>%1" ).arg( file ) );
253 TQString query = url.query(), anchor;
256 if (!query.isEmpty())
257 if (query.left(8) ==
"?anchor=") {
258 anchor = query.mid(8).lower();
262 redirURL.setQuery(TQString::null);
263 redirURL.setHTMLRef(anchor);
264 redirection(redirURL);
268 if (anchor.isEmpty() && url.hasHTMLRef())
269 anchor = url.htmlRef();
271 kdDebug( 7119 ) <<
"anchor: " << anchor << endl;
273 if ( !anchor.isEmpty() )
277 index = mParsed.find( TQRegExp(
"<a name=" ), index);
279 kdDebug( 7119 ) <<
"no anchor\n";
283 if ( mParsed.mid( index, 11 + anchor.length() ).lower() ==
284 TQString(
"<a name=\"%1\">" ).arg( anchor ) )
286 index = mParsed.findRev(
"<FILENAME filename=", index ) +
287 strlen(
"<FILENAME filename=\"" );
288 TQString filename=mParsed.mid( index, 2000 );
289 filename = filename.left( filename.find(
'\"' ) );
290 TQString path = target.path();
291 path = path.left( path.findRev(
'/' ) + 1) + filename;
292 kdDebug( 7119 ) <<
"anchor found in " << path <<endl;
293 target.setPath( path );
306 void HelpProtocol::emitFile(
const KURL& url )
308 infoMessage(i18n(
"Looking up section"));
310 TQString filename = url.path().mid(url.path().findRev(
'/') + 1);
312 int index = mParsed.find(TQString(
"<FILENAME filename=\"%1\"").arg(filename));
314 if ( filename ==
"index.html" ) {
315 data( fromUnicode( mParsed ) );
319 unicodeError( i18n(
"Could not find filename %1 in %2.").arg(filename).arg( url.url() ) );
323 TQString filedata = splitOut(mParsed, index);
324 replaceCharsetHeader( filedata );
326 data( fromUnicode( filedata ) );
327 data( TQByteArray() );
330 void HelpProtocol::mimetype(
const KURL &)
332 mimeType(
"text/html");
338 #define MAX_IPC_SIZE (1024*32)
340 void HelpProtocol::get_file(
const KURL& url )
342 kdDebug( 7119 ) <<
"get_file " << url.url() << endl;
344 TQCString _path( TQFile::encodeName(url.path()));
346 if ( ::stat( _path.data(), &buff ) == -1 ) {
347 if ( errno == EACCES )
348 error( KIO::ERR_ACCESS_DENIED, url.path() );
350 error( KIO::ERR_DOES_NOT_EXIST, url.path() );
354 if ( S_ISDIR( buff.st_mode ) ) {
355 error( KIO::ERR_IS_DIRECTORY, url.path() );
358 if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
359 error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
363 int fd = open( _path.data(), O_RDONLY);
365 error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
369 totalSize( buff.st_size );
370 int processed_size = 0;
372 char buffer[ MAX_IPC_SIZE ];
377 int n = ::read( fd, buffer, MAX_IPC_SIZE );
382 error( KIO::ERR_COULD_NOT_READ, url.path());
389 array.setRawData(buffer, n);
391 array.resetRawData(buffer, n);
394 processedSize( processed_size );
397 data( TQByteArray() );
401 processedSize( buff.st_size );