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>
28 #include <tdeglobal.h>
29 #include <tdelocale.h>
30 #include <kstandarddirs.h>
31 #include <kinstance.h>
33 #include "tdeio_help.h"
34 #include <libxslt/xsltutils.h>
35 #include <libxslt/transform.h>
38 using namespace TDEIO;
40 TQString 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;
91 TQString 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;
134 void 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 ) ) );
141 HelpProtocol *slave = 0;
143 HelpProtocol::HelpProtocol(
bool ghelp,
const TQCString &pool,
const TQCString &app )
144 : SlaveBase( ghelp ?
"ghelp" :
"help", pool, app ), mGhelp( ghelp )
149 void 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 );
314 void 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() );
338 void HelpProtocol::mimetype(
const KURL &)
340 mimeType(
"text/html");
346 #define MAX_IPC_SIZE (1024*32)
348 void 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 );