• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdoctools
 

kdoctools

  • kdoctools
kio_help.cpp
1 #include <config.h>
2 
3 #ifdef HAVE_SYS_TYPES_H
4 # include <sys/types.h>
5 #endif
6 #ifdef HAVE_SYS_STAT_H
7 # include <sys/stat.h>
8 #endif
9 
10 #include <errno.h>
11 #include <fcntl.h>
12 #ifdef HAVE_STDIO_H
13 # include <stdio.h>
14 #endif
15 #ifdef HAVE_STDLIB_H
16 # include <stdlib.h>
17 #endif
18 
19 #include <tqvaluelist.h>
20 #include <tqfileinfo.h>
21 #include <tqfile.h>
22 #include <tqtextstream.h>
23 #include <tqregexp.h>
24 #include <tqtextcodec.h>
25 
26 #include <kdebug.h>
27 #include <kurl.h>
28 #include <kglobal.h>
29 #include <klocale.h>
30 #include <kstandarddirs.h>
31 #include <kinstance.h>
32 
33 #include "kio_help.h"
34 #include <libxslt/xsltutils.h>
35 #include <libxslt/transform.h>
36 #include "xslt.h"
37 
38 using namespace KIO;
39 
40 TQString HelpProtocol::langLookup(const TQString& fname)
41 {
42  TQStringList search;
43 
44  // assemble the local search paths
45  const TQStringList localDoc = KGlobal::dirs()->resourceDirs("html") + KGlobal::dirs()->resourceDirs("html-bundle");
46 
47  TQStringList langs = KGlobal::locale()->languageList();
48  langs.append( "en" );
49  langs.remove( "C" );
50 
51  // this is kind of compat hack as we install our docs in en/ but the
52  // default language is en_US
53  for (TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it)
54  if ( *it == "en_US" )
55  *it = "en";
56 
57  // look up the different languages
58  int ldCount = localDoc.count();
59  for (int id=0; id < ldCount; id++)
60  {
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));
64  }
65 
66  // try to locate the file
67  TQStringList::Iterator it;
68  for (it = search.begin(); it != search.end(); ++it)
69  {
70  kdDebug( 7119 ) << "Looking for help in: " << *it << endl;
71 
72  TQFileInfo info(*it);
73  if (info.exists() && info.isFile() && info.isReadable())
74  return *it;
75 
76  if ( ( *it ).right( 5 ) == ".html" )
77  {
78  TQString file = (*it).left((*it).findRev('/')) + "/index.docbook";
79  kdDebug( 7119 ) << "Looking for help in: " << file << endl;
80  info.setFile(file);
81  if (info.exists() && info.isFile() && info.isReadable())
82  return *it;
83  }
84  }
85 
86 
87  return TQString::null;
88 }
89 
90 
91 TQString HelpProtocol::lookupFile(const TQString &fname,
92  const TQString &query, bool &redirect)
93 {
94  redirect = false;
95 
96  TQString path, result;
97 
98  path = fname;
99 
100  result = langLookup(path);
101  if (result.isEmpty())
102  {
103  result = langLookup(path+"/index.html");
104  if (!result.isEmpty())
105  {
106  KURL red( "help:/" );
107  red.setPath( path + "/index.html" );
108  red.setQuery( query );
109  redirection(red);
110  kdDebug( 7119 ) << "redirect to " << red.url() << endl;
111  redirect = true;
112  }
113  else
114  {
115  unicodeError( i18n("There is no documentation available for %1." ).arg(path) );
116  finished();
117  return TQString::null;
118  }
119  } else
120  kdDebug( 7119 ) << "result " << result << endl;
121 
122  return result;
123 }
124 
125 
126 void HelpProtocol::unicodeError( const TQString &t )
127 {
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 ) ) );
131 }
132 
133 HelpProtocol *slave = 0;
134 
135 HelpProtocol::HelpProtocol( bool ghelp, const TQCString &pool, const TQCString &app )
136  : SlaveBase( ghelp ? "ghelp" : "help", pool, app ), mGhelp( ghelp )
137 {
138  slave = this;
139 }
140 
141 void HelpProtocol::get( const KURL& url )
142 {
143  kdDebug( 7119 ) << "get: path=" << url.path()
144  << " query=" << url.query() << endl;
145 
146  bool redirect;
147  TQString doc;
148  doc = url.path();
149 
150  if ( !mGhelp ) {
151  if (doc.at(0) != '/')
152  doc = doc.prepend('/');
153 
154  if (doc.at(doc.length() - 1) == '/')
155  doc += "index.html";
156  }
157 
158  infoMessage(i18n("Looking up correct file"));
159 
160  if ( !mGhelp ) {
161  doc = lookupFile(doc, url.query(), redirect);
162 
163  if (redirect)
164  {
165  finished();
166  return;
167  }
168  }
169 
170  if (doc.isEmpty())
171  {
172  error( KIO::ERR_DOES_NOT_EXIST, url.url() );
173  return;
174  }
175 
176  mimeType("text/html");
177  KURL target;
178  target.setPath(doc);
179  if (url.hasHTMLRef())
180  target.setHTMLRef(url.htmlRef());
181 
182  kdDebug( 7119 ) << "target " << target.url() << endl;
183 
184  TQString file = target.path();
185 
186  if ( mGhelp ) {
187  if ( file.right( 4 ) != ".xml" ) {
188  get_file( target );
189  return;
190  }
191  } else {
192  TQString docbook_file = file.left(file.findRev('/')) + "/index.docbook";
193  if (!KStandardDirs::exists(file)) {
194  file = docbook_file;
195  } else {
196  TQFileInfo fi(file);
197  if (fi.isDir()) {
198  file = file + "/index.docbook";
199  } else {
200  if ( file.right( 5 ) != ".html" || !compareTimeStamps( file, docbook_file ) ) {
201  get_file( target );
202  return;
203  } else
204  file = docbook_file;
205  }
206  }
207  }
208 
209  infoMessage(i18n("Preparing document"));
210 
211  if ( mGhelp ) {
212  TQString xsl = "customization/kde-nochunk.xsl";
213  mParsed = transform(file, locate("dtd", xsl));
214 
215  kdDebug( 7119 ) << "parsed " << mParsed.length() << endl;
216 
217  if (mParsed.isEmpty()) {
218  unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) );
219  } else {
220  int pos1 = mParsed.find( "charset=" );
221  if ( pos1 > 0 ) {
222  int pos2 = mParsed.find( '"', pos1 );
223  if ( pos2 > 0 ) {
224  mParsed.replace( pos1, pos2 - pos1, "charset=UTF-8" );
225  }
226  }
227  data( mParsed.utf8() );
228  }
229  } else {
230 
231  kdDebug( 7119 ) << "look for cache for " << file << endl;
232 
233  mParsed = lookForCache( file );
234 
235  kdDebug( 7119 ) << "cached parsed " << mParsed.length() << endl;
236 
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",
243  "kio_help" + cache +
244  "cache.bz2" ) );
245  }
246  } else infoMessage( i18n( "Using cached version" ) );
247 
248  kdDebug( 7119 ) << "parsed " << mParsed.length() << endl;
249 
250  if (mParsed.isEmpty()) {
251  unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) );
252  } else {
253  TQString query = url.query(), anchor;
254 
255  // if we have a query, look if it contains an anchor
256  if (!query.isEmpty())
257  if (query.left(8) == "?anchor=") {
258  anchor = query.mid(8).lower();
259 
260  KURL redirURL(url);
261 
262  redirURL.setQuery(TQString::null);
263  redirURL.setHTMLRef(anchor);
264  redirection(redirURL);
265  finished();
266  return;
267  }
268  if (anchor.isEmpty() && url.hasHTMLRef())
269  anchor = url.htmlRef();
270 
271  kdDebug( 7119 ) << "anchor: " << anchor << endl;
272 
273  if ( !anchor.isEmpty() )
274  {
275  int index = 0;
276  while ( true ) {
277  index = mParsed.find( TQRegExp( "<a name=" ), index);
278  if ( index == -1 ) {
279  kdDebug( 7119 ) << "no anchor\n";
280  break; // use whatever is the target, most likely index.html
281  }
282 
283  if ( mParsed.mid( index, 11 + anchor.length() ).lower() ==
284  TQString( "<a name=\"%1\">" ).arg( anchor ) )
285  {
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 );
294  break;
295  }
296  index++;
297  }
298  }
299  emitFile( target );
300  }
301  }
302 
303  finished();
304 }
305 
306 void HelpProtocol::emitFile( const KURL& url )
307 {
308  infoMessage(i18n("Looking up section"));
309 
310  TQString filename = url.path().mid(url.path().findRev('/') + 1);
311 
312  int index = mParsed.find(TQString("<FILENAME filename=\"%1\"").arg(filename));
313  if (index == -1) {
314  if ( filename == "index.html" ) {
315  data( fromUnicode( mParsed ) );
316  return;
317  }
318 
319  unicodeError( i18n("Could not find filename %1 in %2.").arg(filename).arg( url.url() ) );
320  return;
321  }
322 
323  TQString filedata = splitOut(mParsed, index);
324  replaceCharsetHeader( filedata );
325 
326  data( fromUnicode( filedata ) );
327  data( TQByteArray() );
328 }
329 
330 void HelpProtocol::mimetype( const KURL &)
331 {
332  mimeType("text/html");
333  finished();
334 }
335 
336 // Copied from kio_file to avoid redirects
337 
338 #define MAX_IPC_SIZE (1024*32)
339 
340 void HelpProtocol::get_file( const KURL& url )
341 {
342  kdDebug( 7119 ) << "get_file " << url.url() << endl;
343 
344  TQCString _path( TQFile::encodeName(url.path()));
345  struct stat buff;
346  if ( ::stat( _path.data(), &buff ) == -1 ) {
347  if ( errno == EACCES )
348  error( KIO::ERR_ACCESS_DENIED, url.path() );
349  else
350  error( KIO::ERR_DOES_NOT_EXIST, url.path() );
351  return;
352  }
353 
354  if ( S_ISDIR( buff.st_mode ) ) {
355  error( KIO::ERR_IS_DIRECTORY, url.path() );
356  return;
357  }
358  if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
359  error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
360  return;
361  }
362 
363  int fd = open( _path.data(), O_RDONLY);
364  if ( fd < 0 ) {
365  error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
366  return;
367  }
368 
369  totalSize( buff.st_size );
370  int processed_size = 0;
371 
372  char buffer[ MAX_IPC_SIZE ];
373  TQByteArray array;
374 
375  while( 1 )
376  {
377  int n = ::read( fd, buffer, MAX_IPC_SIZE );
378  if (n == -1)
379  {
380  if (errno == EINTR)
381  continue;
382  error( KIO::ERR_COULD_NOT_READ, url.path());
383  close(fd);
384  return;
385  }
386  if (n == 0)
387  break; // Finished
388 
389  array.setRawData(buffer, n);
390  data( array );
391  array.resetRawData(buffer, n);
392 
393  processed_size += n;
394  processedSize( processed_size );
395  }
396 
397  data( TQByteArray() );
398 
399  close( fd );
400 
401  processedSize( buff.st_size );
402 
403  finished();
404 }
KIO

kdoctools

Skip menu "kdoctools"
  • Main Page
  • File List
  • Related Pages

kdoctools

Skip menu "kdoctools"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdoctools by doxygen 1.8.11
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |