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

kdoctools

  • kdoctools
tdeio_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 <tdeglobal.h>
29 #include <tdelocale.h>
30 #include <kstandarddirs.h>
31 #include <kinstance.h>
32 
33 #include "tdeio_help.h"
34 #include <libxslt/xsltutils.h>
35 #include <libxslt/transform.h>
36 #include "xslt.h"
37 
38 using namespace TDEIO;
39 
40 TQString HelpProtocol::langLookup(const TQString &fname)
41 {
42  TQStringList search;
43 
44  // assemble the local search paths
45  const TQStringList localDoc = TDEGlobal::dirs()->resourceDirs("html") + TDEGlobal::dirs()->resourceDirs("html-bundle");
46 
47  TQStringList langs = TDEGlobal::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, const TQString &query, bool &redirect)
92 {
93  redirect = false;
94  TQString result = langLookup(fname);
95  if (result.isEmpty())
96  {
97  result = langLookup(fname+"/index.html");
98  if (!result.isEmpty())
99  {
100  KURL red("help:/");
101  red.setPath( fname+"/index.html" );
102  red.setQuery( query );
103  redirection(red);
104  kdDebug( 7119 ) << "redirect to " << red.url() << endl;
105  redirect = true;
106  }
107  else
108  {
109  const TQString helpNotFound("khelpcenter/helpnotfound/index.html");
110  result = langLookup(helpNotFound);
111  if (!result.isEmpty())
112  {
113  KURL red("help:/");
114  red.setPath(helpNotFound);
115  red.setQuery(query);
116  redirection(red);
117  kdDebug( 7119 ) << "redirect to " << red.url() << endl;
118  redirect = true;
119  }
120  else
121  {
122  unicodeError(i18n("Sorry, there is no documentation available at all for %1." ).arg(fname));
123  finished();
124  return TQString::null;
125  }
126  }
127  } else
128  kdDebug( 7119 ) << "result " << result << endl;
129 
130  return result;
131 }
132 
133 
134 void HelpProtocol::unicodeError( const TQString &t )
135 {
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 ) ) );
139 }
140 
141 HelpProtocol *slave = 0;
142 
143 HelpProtocol::HelpProtocol( bool ghelp, const TQCString &pool, const TQCString &app )
144  : SlaveBase( ghelp ? "ghelp" : "help", pool, app ), mGhelp( ghelp )
145 {
146  slave = this;
147 }
148 
149 void HelpProtocol::get( const KURL& url )
150 {
151  kdDebug( 7119 ) << "get: path=" << url.path()
152  << " query=" << url.query() << endl;
153 
154  bool redirect;
155  TQString doc;
156  doc = url.path();
157 
158  if ( !mGhelp ) {
159  if (doc.at(0) != '/')
160  doc = doc.prepend('/');
161 
162  if (doc.at(doc.length() - 1) == '/')
163  doc += "index.html";
164  }
165 
166  infoMessage(i18n("Looking up correct file"));
167 
168  if ( !mGhelp ) {
169  doc = lookupFile(doc, url.query(), redirect);
170 
171  if (redirect)
172  {
173  finished();
174  return;
175  }
176  }
177 
178  if (doc.isEmpty())
179  {
180  error( TDEIO::ERR_DOES_NOT_EXIST, url.url() );
181  return;
182  }
183 
184  mimeType("text/html");
185  KURL target;
186  target.setPath(doc);
187  if (url.hasHTMLRef())
188  target.setHTMLRef(url.htmlRef());
189 
190  kdDebug( 7119 ) << "target " << target.url() << endl;
191 
192  TQString file = target.path();
193 
194  if ( mGhelp ) {
195  if ( file.right( 4 ) != ".xml" ) {
196  get_file( target );
197  return;
198  }
199  } else {
200  TQString docbook_file = file.left(file.findRev('/')) + "/index.docbook";
201  if (!TDEStandardDirs::exists(file)) {
202  file = docbook_file;
203  } else {
204  TQFileInfo fi(file);
205  if (fi.isDir()) {
206  file = file + "/index.docbook";
207  } else {
208  if ( file.right( 5 ) != ".html" || !compareTimeStamps( file, docbook_file ) ) {
209  get_file( target );
210  return;
211  } else
212  file = docbook_file;
213  }
214  }
215  }
216 
217  infoMessage(i18n("Preparing document"));
218 
219  if ( mGhelp ) {
220  TQString xsl = "customization/tde-nochunk.xsl";
221  mParsed = transform(file, locate("dtd", xsl));
222 
223  kdDebug( 7119 ) << "parsed " << mParsed.length() << endl;
224 
225  if (mParsed.isEmpty()) {
226  unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) );
227  } else {
228  int pos1 = mParsed.find( "charset=" );
229  if ( pos1 > 0 ) {
230  int pos2 = mParsed.find( '"', pos1 );
231  if ( pos2 > 0 ) {
232  mParsed.replace( pos1, pos2 - pos1, "charset=UTF-8" );
233  }
234  }
235  data( mParsed.utf8() );
236  }
237  } else {
238 
239  kdDebug( 7119 ) << "look for cache for " << file << endl;
240 
241  mParsed = lookForCache( file );
242 
243  kdDebug( 7119 ) << "cached parsed " << mParsed.length() << endl;
244 
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 +
252  "cache.bz2" ) );
253  }
254  } else infoMessage( i18n( "Using cached version" ) );
255 
256  kdDebug( 7119 ) << "parsed " << mParsed.length() << endl;
257 
258  if (mParsed.isEmpty()) {
259  unicodeError( i18n( "The requested help file could not be parsed:<br>%1" ).arg( file ) );
260  } else {
261  TQString query = url.query(), anchor;
262 
263  // if we have a query, look if it contains an anchor
264  if (!query.isEmpty())
265  if (query.left(8) == "?anchor=") {
266  anchor = query.mid(8).lower();
267 
268  KURL redirURL(url);
269 
270  redirURL.setQuery(TQString::null);
271  redirURL.setHTMLRef(anchor);
272  redirection(redirURL);
273  finished();
274  return;
275  }
276  if (anchor.isEmpty() && url.hasHTMLRef())
277  anchor = url.htmlRef();
278 
279  kdDebug( 7119 ) << "anchor: " << anchor << endl;
280 
281  if ( !anchor.isEmpty() )
282  {
283  int index = 0;
284  while ( true ) {
285  index = mParsed.find( TQRegExp( "<a name=" ), index);
286  if ( index == -1 ) {
287  kdDebug( 7119 ) << "no anchor\n";
288  break; // use whatever is the target, most likely index.html
289  }
290 
291  if ( mParsed.mid( index, 11 + anchor.length() ).lower() ==
292  TQString( "<a name=\"%1\">" ).arg( anchor ) )
293  {
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 );
302  break;
303  }
304  index++;
305  }
306  }
307  emitFile( target );
308  }
309  }
310 
311  finished();
312 }
313 
314 void HelpProtocol::emitFile( const KURL& url )
315 {
316  infoMessage(i18n("Looking up section"));
317 
318  TQString filename = url.path().mid(url.path().findRev('/') + 1);
319 
320  int index = mParsed.find(TQString("<FILENAME filename=\"%1\"").arg(filename));
321  if (index == -1) {
322  if ( filename == "index.html" ) {
323  data( fromUnicode( mParsed ) );
324  return;
325  }
326 
327  unicodeError( i18n("Could not find filename %1 in %2.").arg(filename).arg( url.url() ) );
328  return;
329  }
330 
331  TQString filedata = splitOut(mParsed, index);
332  replaceCharsetHeader( filedata );
333 
334  data( fromUnicode( filedata ) );
335  data( TQByteArray() );
336 }
337 
338 void HelpProtocol::mimetype( const KURL &)
339 {
340  mimeType("text/html");
341  finished();
342 }
343 
344 // Copied from tdeio_file to avoid redirects
345 
346 #define MAX_IPC_SIZE (1024*32)
347 
348 void HelpProtocol::get_file( const KURL& url )
349 {
350  kdDebug( 7119 ) << "get_file " << url.url() << endl;
351 
352  TQCString _path( TQFile::encodeName(url.path()));
353  struct stat buff;
354  if ( ::stat( _path.data(), &buff ) == -1 ) {
355  if ( errno == EACCES )
356  error( TDEIO::ERR_ACCESS_DENIED, url.path() );
357  else
358  error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
359  return;
360  }
361 
362  if ( S_ISDIR( buff.st_mode ) ) {
363  error( TDEIO::ERR_IS_DIRECTORY, url.path() );
364  return;
365  }
366  if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
367  error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
368  return;
369  }
370 
371  int fd = open( _path.data(), O_RDONLY);
372  if ( fd < 0 ) {
373  error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
374  return;
375  }
376 
377  totalSize( buff.st_size );
378  int processed_size = 0;
379 
380  char buffer[ MAX_IPC_SIZE ];
381  TQByteArray array;
382 
383  while( 1 )
384  {
385  int n = ::read( fd, buffer, MAX_IPC_SIZE );
386  if (n == -1)
387  {
388  if (errno == EINTR)
389  continue;
390  error( TDEIO::ERR_COULD_NOT_READ, url.path());
391  close(fd);
392  return;
393  }
394  if (n == 0)
395  break; // Finished
396 
397  array.setRawData(buffer, n);
398  data( array );
399  array.resetRawData(buffer, n);
400 
401  processed_size += n;
402  processedSize( processed_size );
403  }
404 
405  data( TQByteArray() );
406 
407  close( fd );
408 
409  processedSize( buff.st_size );
410 
411  finished();
412 }
TDEIO

kdoctools

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

kdoctools

Skip menu "kdoctools"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kdoctools by doxygen 1.8.8
This website is maintained by Timothy Pearson.