TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

meinproc.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include <config.h>
  2. #include <string.h>
  3. #include <sys/time.h>
  4. #include <unistd.h>
  5. #include <libxml/xmlversion.h>
  6. #include <libxml/xmlmemory.h>
  7. #include <libxml/debugXML.h>
  8. #include <libxml/HTMLtree.h>
  9. #include <libxml/xmlIO.h>
  10. #include <libxml/parserInternals.h>
  11. #include <libxslt/xsltconfig.h>
  12. #include <libxslt/xsltInternals.h>
  13. #include <libxslt/transform.h>
  14. #include <libxslt/xsltutils.h>
  15. #include <tqstring.h>
  16. #include <kstandarddirs.h>
  17. #include <kinstance.h>
  18. #include <xslt.h>
  19. #include <tqfile.h>
  20. #include <tqdir.h>
  21. #include <tdecmdlineargs.h>
  22. #include <tdelocale.h>
  23. #include <tdeaboutdata.h>
  24. #include <stdlib.h>
  25. #include <kdebug.h>
  26. #include <tqtextcodec.h>
  27. #include <tqfileinfo.h>
  28. #include <kprocess.h>
  29. #include <tqvaluevector.h>
  30. extern int xmlLoadExtDtdDefaultValue;
  31. class MyPair {
  32. public:
  33. TQString word;
  34. int base;};
  35. typedef TQValueList<MyPair> PairList;
  36. void parseEntry(PairList &list, xmlNodePtr cur, int base)
  37. {
  38. if ( !cur )
  39. return;
  40. base += atoi( ( const char* )xmlGetProp(cur, ( const xmlChar* )"header") );
  41. if ( base > 10 ) // 10 is the maximum
  42. base = 10;
  43. /* We don't care what the top level element name is */
  44. cur = cur->xmlChildrenNode;
  45. while (cur != NULL) {
  46. if ( cur->type == XML_TEXT_NODE ) {
  47. TQString words = TQString::fromUtf8( ( char* )cur->content );
  48. TQStringList wlist = TQStringList::split( ' ', words.simplifyWhiteSpace() );
  49. for ( TQStringList::ConstIterator it = wlist.begin();
  50. it != wlist.end(); ++it )
  51. {
  52. MyPair m;
  53. m.word = *it;
  54. m.base = base;
  55. list.append( m );
  56. }
  57. } else if ( !xmlStrcmp( cur->name, (const xmlChar *) "entry") )
  58. parseEntry( list, cur, base );
  59. cur = cur->next;
  60. }
  61. }
  62. static TDECmdLineOptions options[] =
  63. {
  64. { "stylesheet <xsl>", I18N_NOOP( "Stylesheet to use" ), 0 },
  65. { "stdout", I18N_NOOP( "Output whole document to stdout" ), 0 },
  66. { "o", 0, 0 },
  67. { "output <file>", I18N_NOOP("Output whole document to file" ), 0 },
  68. { "htdig", I18N_NOOP( "Create a ht://dig compatible index" ), 0 },
  69. { "check", I18N_NOOP( "Check the document for validity" ), 0 },
  70. { "cache <file>", I18N_NOOP( "Create a cache file for the document" ), 0},
  71. { "srcdir <dir>", I18N_NOOP( "Set the srcdir, for tdelibs" ), 0},
  72. { "param <key>=<value>", I18N_NOOP( "Parameters to pass to the stylesheet" ), 0},
  73. { "+xml", I18N_NOOP("The file to transform"), 0},
  74. TDECmdLineLastOption // End of options.
  75. };
  76. int main(int argc, char **argv) {
  77. // xsltSetGenericDebugFunc(stderr, NULL);
  78. TDEAboutData aboutData( "meinproc", I18N_NOOP("XML-Translator" ),
  79. "$Revision$",
  80. I18N_NOOP("TDE Translator for XML"));
  81. TDECmdLineArgs::init(argc, argv, &aboutData);
  82. TDECmdLineArgs::addCmdLineOptions( options );
  83. TDELocale::setMainCatalogue("tdeio_help");
  84. TDEInstance ins("meinproc");
  85. TDEGlobal::locale();
  86. TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
  87. if ( args->count() != 1 ) {
  88. args->usage();
  89. return ( 1 );
  90. }
  91. // Need to set SRCDIR before calling fillInstance
  92. TQString srcdir;
  93. if ( args->isSet( "srcdir" ) )
  94. srcdir = TQDir( TQFile::decodeName( args->getOption( "srcdir" ) ) ).absPath();
  95. fillInstance(ins,srcdir);
  96. LIBXML_TEST_VERSION
  97. TQString checkFilename = TQFile::decodeName(args->arg( 0 ));
  98. TQFileInfo checkFile(checkFilename);
  99. if (!checkFile.exists())
  100. {
  101. kdError() << "File '" << checkFilename << "' does not exist." << endl;
  102. return ( 2 );
  103. }
  104. if (!checkFile.isFile())
  105. {
  106. kdError() << "'" << checkFilename << "' is not a file." << endl;
  107. return ( 2 );
  108. }
  109. if (!checkFile.isReadable())
  110. {
  111. kdError() << "File '" << checkFilename << "' is not readable." << endl;
  112. return ( 2 );
  113. }
  114. if ( args->isSet( "check" ) ) {
  115. #if !defined(PATH_MAX) && defined(__GLIBC__)
  116. char *pwd_buffer;
  117. #else
  118. char pwd_buffer[PATH_MAX];
  119. #endif
  120. TQFileInfo file( TQFile::decodeName(args->arg( 0 )) );
  121. #if !defined(PATH_MAX) && defined(__GLIBC__)
  122. if ( !(pwd_buffer = getcwd( NULL, 0 ) ) )
  123. #else
  124. if ( !getcwd( pwd_buffer, sizeof(pwd_buffer) - 1 ) )
  125. #endif
  126. {
  127. kdError() << "getcwd failed." << endl;
  128. return 2;
  129. }
  130. TQString catalogs;
  131. catalogs += locate( "dtd", "customization/catalog" );
  132. catalogs += " ";
  133. catalogs += locate( "dtd", "docbook/xml-dtd-4.1.2/docbook.cat" );
  134. setenv( "SGML_CATALOG_FILES", TQFile::encodeName( catalogs ).data(), 1);
  135. TQString exe;
  136. #if defined( XMLLINT )
  137. exe = XMLLINT;
  138. #endif
  139. if ( (::access( TQFile::encodeName( exe ), X_OK )!=0) ) {
  140. exe = TDEStandardDirs::findExe( "xmllint" );
  141. if (exe.isEmpty())
  142. exe = locate( "exe", "xmllint" );
  143. }
  144. if ( ::access( TQFile::encodeName( exe ), X_OK )==0 ) {
  145. chdir( TQFile::encodeName( file.dirPath( true ) ) );
  146. TQString cmd = exe;
  147. cmd += " --catalogs --valid --noout ";
  148. cmd += TDEProcess::quote(file.fileName());
  149. cmd += " 2>&1";
  150. FILE *xmllint = popen( TQFile::encodeName( cmd ), "r");
  151. char buf[ 512 ];
  152. bool noout = true;
  153. unsigned int n;
  154. while ( ( n = fread(buf, 1, sizeof( buf ), xmllint ) ) ) {
  155. noout = false;
  156. buf[ n ] = '\0';
  157. fputs( buf, stderr );
  158. }
  159. pclose( xmllint );
  160. chdir( pwd_buffer );
  161. if ( !noout ) {
  162. #if !defined(PATH_MAX) && defined(__GLIBC__)
  163. free( pwd_buffer );
  164. #endif
  165. return 1;
  166. }
  167. } else {
  168. kdWarning() << "couldn't find xmllint" << endl;
  169. }
  170. #if !defined(PATH_MAX) && defined(__GLIBC__)
  171. free( pwd_buffer );
  172. #endif
  173. }
  174. xmlSubstituteEntitiesDefault(1);
  175. xmlLoadExtDtdDefaultValue = 1;
  176. TQValueVector<const char *> params;
  177. if (args->isSet( "output" ) ) {
  178. params.append( tqstrdup( "outputFile" ) );
  179. params.append( tqstrdup( TQString(TQFile::decodeName( args->getOption( "output" ) )).latin1() ) );
  180. }
  181. {
  182. const QCStringList paramList = args->getOptionList( "param" );
  183. QCStringList::ConstIterator it = paramList.begin();
  184. QCStringList::ConstIterator end = paramList.end();
  185. for ( ; it != end; ++it ) {
  186. const TQCString tuple = *it;
  187. const int ch = tuple.find( '=' );
  188. if ( ch == -1 ) {
  189. kdError() << "Key-Value tuple '" << tuple << "' lacks a '='!" << endl;
  190. return( 2 );
  191. }
  192. params.append( tqstrdup( tuple.left( ch ) ) );
  193. params.append( tqstrdup( tuple.mid( ch + 1 ) ) );
  194. }
  195. }
  196. params.append( NULL );
  197. bool index = args->isSet( "htdig" );
  198. TQString tss = args->getOption( "stylesheet" );
  199. if ( tss.isEmpty() )
  200. tss = "customization/kde-chunk.xsl";
  201. if ( index )
  202. tss = "customization/htdig_index.xsl" ;
  203. tss = locate( "dtd", tss );
  204. if ( index ) {
  205. xsltStylesheetPtr style_sheet =
  206. xsltParseStylesheetFile((const xmlChar *)tss.latin1());
  207. if (style_sheet != NULL) {
  208. xmlDocPtr doc = xmlParseFile( TQFile::encodeName( args->arg( 0 ) ) );
  209. xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, &params[0]);
  210. xmlFreeDoc(doc);
  211. xsltFreeStylesheet(style_sheet);
  212. if (res != NULL) {
  213. xmlNodePtr cur = xmlDocGetRootElement(res);
  214. if (!cur || xmlStrcmp(cur->name, (const xmlChar *) "entry")) {
  215. fprintf(stderr,"document of the wrong type, root node != entry");
  216. xmlFreeDoc(res);
  217. return(1);
  218. }
  219. PairList list;
  220. parseEntry( list, cur, 0 );
  221. int wi = 0;
  222. for ( PairList::ConstIterator it = list.begin(); it != list.end();
  223. ++it, ++wi )
  224. fprintf( stdout, "w\t%s\t%d\t%d\n", ( *it ).word.utf8().data(),
  225. 1000*wi/(int)list.count(), ( *it ).base );
  226. xmlFreeDoc(res);
  227. } else {
  228. kdDebug() << "couldn't parse document " << args->arg( 0 ) << endl;
  229. }
  230. } else {
  231. kdDebug() << "couldn't parse style sheet " << tss << endl;
  232. }
  233. } else {
  234. TQString output = transform(args->arg( 0 ) , tss, params);
  235. if (output.isEmpty()) {
  236. fprintf(stderr, "unable to parse %s\n", args->arg( 0 ));
  237. return(1);
  238. }
  239. TQString cache = args->getOption( "cache" );
  240. if ( !cache.isEmpty() ) {
  241. if ( !saveToCache( output, cache ) ) {
  242. kdError() << TQString(i18n( "Could not write to cache file %1." ).arg( cache )) << endl;
  243. }
  244. goto end;
  245. }
  246. if (output.find( "<FILENAME " ) == -1 || args->isSet( "stdout" ) || args->isSet("output") )
  247. {
  248. TQFile file;
  249. if (args->isSet( "stdout" ) ) {
  250. file.open( IO_WriteOnly, stdout );
  251. } else {
  252. if (args->isSet( "output" ) )
  253. file.setName( TQFile::decodeName(args->getOption( "output" )));
  254. else
  255. file.setName( "index.html" );
  256. file.open(IO_WriteOnly);
  257. }
  258. replaceCharsetHeader( output );
  259. TQCString data = output.local8Bit();
  260. file.writeBlock(data.data(), data.length());
  261. file.close();
  262. } else {
  263. int index = 0;
  264. while (true) {
  265. index = output.find("<FILENAME ", index);
  266. if (index == -1)
  267. break;
  268. int filename_index = index + strlen("<FILENAME filename=\"");
  269. TQString filename = output.mid(filename_index,
  270. output.find("\"", filename_index) -
  271. filename_index);
  272. TQString filedata = splitOut(output, index);
  273. TQFile file(filename);
  274. file.open(IO_WriteOnly);
  275. replaceCharsetHeader( filedata );
  276. TQCString data = fromUnicode( filedata );
  277. file.writeBlock(data.data(), data.length());
  278. file.close();
  279. index += 8;
  280. }
  281. }
  282. }
  283. end:
  284. xmlCleanupParser();
  285. xmlMemoryDump();
  286. return(0);
  287. }