PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/add-ons/modsp/sp.php

https://github.com/jcplat/console-seolan
PHP | 691 lines | 599 code | 44 blank | 48 comment | 27 complexity | 8d441d83e1727e21b4e66d99ed9c00c9 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. //error_reporting(E_ALL);
  3. /*
  4. * Copyright (C) 2004 BYS Promotion, France
  5. *
  6. * Web: http://www.bys-promotion.com/
  7. * http://sourceforge.net/projects/comarquage/
  8. * http://comarquage.sourceforge.net/
  9. *
  10. * Coordinator: Daniel BODEA (daniel.bodea@bys-promotion.com)
  11. *
  12. * This software package is released under the terms of the Q Public License
  13. * version 1.0. The full text of the license is available in the LICENSE file
  14. * that is bundled with this distribution.
  15. *
  16. * The code, or any part thereof, can only be redistributed if the statements
  17. * above, including this one, are included unchanged in all redistributed
  18. * materials.
  19. *
  20. */
  21. /* This class is built so that it can be subclassed for advanced logic
  22. modifications and improvements.
  23. */
  24. class ServicePublic_V2
  25. {
  26. /* Object configuration variables, updated from configuration files and
  27. inside the constructor. Dynamic values are computed in the constructor. */
  28. var $aParams = array(
  29. 'xml_server' => 'http://lecomarquage.service-public.fr/xml2v2',
  30. 'default_xml_file' => 'Themes.xml',
  31. 'default_xsl_file' => 'spThemes.xsl',
  32. 'local_timeout' => 259200, /* 60*60*24*3 */
  33. 'root_path' => NULL,
  34. 'images_path' => NULL,
  35. 'error_email' => NULL,
  36. 'handle_not_contained' => TRUE,
  37. 'html_error_template' => array(
  38. '<div align="center"><div style="border-left: 3px solid red; ',
  39. 'padding-left:5px;text-align:left;" nowrap>%s</div></div>',
  40. ),
  41. );
  42. /* Constructor. Parameter is an array of configuration variables, a folder
  43. containing the default configuration file or the full path of a custom
  44. configuration file.
  45. */
  46. function __construct($vConfig = NULL)
  47. {
  48. /* TODO: Merge from a global variable too. */
  49. $bMergeConfig = (boolean)(
  50. $this->_mergeConfigFrom(dirname(__FILE__)) &&
  51. (
  52. getcwd() == dirname(__FILE__) ||
  53. $this->_mergeConfigFrom($this->_sConfigFile)
  54. ) && (
  55. is_null($vConfig) ||
  56. $this->_mergeConfigFrom($vConfig)
  57. ) && (
  58. !isset($this->_aParams) ||
  59. $this->_mergeConfigFrom($this->_aParams)
  60. )
  61. );
  62. /* TODO: Test and continue if no show stoppers. */
  63. if (!$bMergeConfig) {
  64. $this->_error("impossible de créer un objet <b>".get_class($this)."</b> ".
  65. "car une erreur est survenue lors de sa configuration initiale",
  66. E_USER_ERROR);
  67. return;
  68. }
  69. if (!defined(TZR_COMARQUAGE_CACHE_DIR))
  70. define('TZR_COMARQUAGE_CACHE_DIR',TZR_VAR2_DIR.'modsp/');
  71. if (isset($this->_aParams)) unset($this->_aParams);
  72. is_null($this->aParams['root_path']) and
  73. $this->aParams['root_path'] = dirname(__FILE__);
  74. }
  75. /* Make sure the specified file is on disk, with or without its related
  76. ressources.
  77. */
  78. function prepareXMLFile($aFileParams, $bRelated = TRUE)
  79. {
  80. if (($bExists = file_exists($aFileParams['xml_full_path'])) &&
  81. time() - filemtime($aFileParams['xml_full_path']) <
  82. $this->aParams['local_timeout']) {
  83. return TRUE;
  84. }
  85. if (!$vFetch = $this->fetchXMLFile($aFileParams)) {
  86. $this->_error("erreur de téléchargement du fichier <b>".
  87. "$aFileParams[xml]</b>; ".(
  88. $bExists ? "l'action continue avec le fichier présent dans le cache ".
  89. "mais la connexion au serveur externe doit ętre rétablie" :
  90. "l'action ne peut pas ętre poursuivie car le fichier n'existe pas ".
  91. "dans le cache"), E_USER_NOTICE);
  92. return $bExists;
  93. }
  94. if ($bRelated && $vFetch == 20 && $aFileParams['xml']{0} != 'M') {
  95. $aRes = $this->extractAssociatedRessources($aFileParams['xml_full_path']);
  96. /* TODO: The full path of a local XML file should be calculated centrally
  97. so that special cases can be handled once only. */
  98. if ($aRes !== FALSE) foreach ($aRes as $v) {
  99. if (!$this->prepareXMLFile(array_merge($aFileParams, array(
  100. 'xml' => $v,
  101. 'xml_full_path'=>TZR_COMARQUAGE_CACHE_DIR.'xml/'.$v)),FALSE)) {
  102. $aRes = FALSE; break;
  103. }
  104. }
  105. /* TODO: Unlink the main XML file ? Continue the action ? The main file
  106. should compile even without its ressources while generating an
  107. XSL error.
  108. Ressources may be recursive. Flag files as incomplete for
  109. further downloading at a later time. Watch out for XSL "missing
  110. related files" errors indicating this state. */
  111. if ($aRes === FALSE) {
  112. $this->_error("impossible de récupérer les ressources associées au ".
  113. "fichier <b>$aFileParams[xml_full_path]</b>");
  114. return FALSE;
  115. }
  116. }
  117. return TRUE;
  118. }
  119. /* Download a remote XML file. Return FALSE on error, 10 if not modified and
  120. 20 if the file was downloaded OK.
  121. */
  122. function fetchXMLFile($aFileParams)
  123. {
  124. /* TODO: This is an extremely light weight HTTP client tailored especially for
  125. the requests of this module. It doesn't understand anything more than
  126. the very basic response codes so it only works in the most basic
  127. environment.
  128. A later version of this function should use a higher level HTTP
  129. handler like the context support and the HTTP built-in wrapper in
  130. PHP 5 or the HTTP libraries in PEAR. */
  131. $sModSince = file_exists($aFileParams['xml_full_path']) ? 'If-Modified-Since: '.
  132. gmdate('r', filemtime($aFileParams['xml_full_path']))."\r\n" : '';
  133. $aURL = parse_url($this->aParams['xml_server']);
  134. if (empty($aURL['host'])) {
  135. $this->_error("l'adresse du serveur XML semble ne pas ętre correcte ('<b>".
  136. $this->aParams['xml_server']."</b>'); vérifiez qu'elle soit au format ".
  137. "HTTP standard complet");
  138. return FALSE;
  139. }
  140. /* HTTP request headers sent to the remote XML server. */
  141. $uu=$aURL['host'].$aURL['path']."/".$aFileParams['xml'];
  142. $hplus="";
  143. if(!empty($sModSince)) $hplus="-H '$sModSince'";
  144. exec(TZR_CURL_PATH." $hplus -I --interface ".TZR_COMARQUAGE_IP.' '.$uu, $aHeaders);
  145. exec(TZR_CURL_PATH." $hplus --interface ".TZR_COMARQUAGE_IP.' '.$uu, $s1);
  146. $sBody=implode("\n",$s1);
  147. if (!ereg('^HTTP[^ ]+ ([[:digit:]]+) (.*)$', $aHeaders[0], $aRegs)) {
  148. $this->_error("erreur d'interprétation de l'en-tęte HTTP ".
  149. "'<b>$aHeaders[0]</b>'");
  150. return FALSE;
  151. }
  152. $sRCode = $aRegs[1]; $sRMessage = $aRegs[2];
  153. unset($aRegs);
  154. /* TODO: Use Apache's error database to consume the return code. */
  155. switch ($sRCode) {
  156. /* Return 10 to signal that the file was not modified. */
  157. case '304': return 10;
  158. case '200':
  159. if (!$fp = fopen($aFileParams['xml_full_path'], 'wb')) {
  160. $this->_error("erreur d'ouverture en écriture du fichier ".
  161. "'<b>$aFileParams[xml_full_path]</b>'");
  162. return FALSE;
  163. }
  164. /* Return 20 if the file has been downloaded OK. */
  165. fwrite($fp, $sBody);
  166. fclose($fp); return 20;
  167. default:
  168. $this->_error("code de réponse inconnu ('<b>$sRCode $sRMessage</b>') ".
  169. "en téléchargeant le fichier '<b>$aFileParams[xml]</b>' du serveur ".
  170. "<b>$aURL[host]</b>");
  171. return FALSE;
  172. }
  173. /* Execution shouldn't reach this point. */
  174. return FALSE;
  175. }
  176. /* Return an array containing the ressource files related to the given
  177. XML file.
  178. */
  179. function extractAssociatedRessources($sXMLFile)
  180. {
  181. $sRessourcesXSL = dirname(__FILE__).'/ressources.xsl';
  182. $oXSL =& new _ServicePublic_XSL_Engine($this, $bRet);
  183. if (!$bRet) return FALSE;
  184. if (($aRessources =& $oXSL->transformXMLFile(
  185. $sXMLFile, $sRessourcesXSL)) === FALSE)
  186. return FALSE;
  187. $aRet = array(); foreach ($aRessources as $v)
  188. if ($sRessource = trim($v)) $aRet[] = $sRessource.'.xml';
  189. return $aRet;
  190. }
  191. /* Get the contents of one compiled XML file.
  192. */
  193. function & compileOnePage($aCallParams)
  194. {
  195. $this->_secureCallParams($aCallParams);
  196. if (!file_exists($aCallParams['xsl_full_path'])) {
  197. $this->_error("la feuille de style XSL ".
  198. "'<b>$aCallParams[xsl]</b>' n'existe pas");
  199. return -10;
  200. }
  201. if (!$this->prepareXMLFile($aCallParams))
  202. return -20;
  203. $this->_prepareCacheParams($aCallParams);
  204. if ($sOutput =& $this->_getCache($aCallParams))
  205. return $sOutput;
  206. /* TODO: Use a stack based error reporting system. */
  207. $oXSL =& new _ServicePublic_XSL_Engine($this, $bRet);
  208. if (!$bRet) return -30;
  209. $aXSLParams = array();
  210. /* TODO: The image path should be calculated differently according to the
  211. location of the XML content and according to the XSL sheets. */
  212. $aXSLParams['REFERER']= TZR_COMARQUAGE_PAGE.'?';
  213. $aXSLParams['PICTOS']= is_null($this->aParams['pictos_path']) ?
  214. dirname($_SERVER['PHP_SELF']).'/pictos/' : $this->aParams['pictos_path'];
  215. $aXSLParams['SITEURL']= $GLOBALS['HOME_ROOT_URL'];
  216. $aXSLParams['IMAGES']= is_null($this->aParams['images_path']) ?
  217. dirname($_SERVER['PHP_SELF']).'/images/' : $this->aParams['images_path'];
  218. $aXSLParams['PIVOTS']= '';
  219. $aXSLParams['XMLURL']= 'http://lecomarquage.service-public.fr/xml2v2/';
  220. $aXSLParams['CATEGORIE']= is_null($this->aParams['pictos_path']) ?
  221. 'particuliers' : $this->aParams['categorie'];
  222. if (($sOutput =& $oXSL->transformXMLFile($aCallParams['xml_full_path'],
  223. $aCallParams['xsl_full_path'], $aXSLParams)) === FALSE) {
  224. $this->_error("le processeur XSLT a retourné une erreur fatale; ".
  225. "l'action ne peut pas continuer");
  226. return -40;
  227. }
  228. $sOutput = implode("\n", $sOutput)."\n";
  229. $this->_setCache($aCallParams, $sOutput);
  230. return $sOutput;
  231. }
  232. function isContained()
  233. {
  234. return TRUE;
  235. /* TODO: The referer header is easy to fake so a stronger one-time-key
  236. authorization scheme needs to be brought in. */
  237. $sRef = (empty($_SERVER['HTTPS']) ? 'http' : 'https').'://'.
  238. $_SERVER['HTTP_HOST'].'/';
  239. if (empty($_SERVER['HTTP_REFERER']) ||
  240. $sRef != substr($_SERVER['HTTP_REFERER'], 0, strlen($sRef))) {
  241. $this->_error("l'appel n'est pas autorisé pour REFERER = ".(
  242. empty($_SERVER['HTTP_REFERER']) ?
  243. '(vide)' : '<b>'.$_SERVER['HTTP_REFERER'].'</b>'));
  244. return FALSE;
  245. }
  246. return TRUE;
  247. }
  248. /* The JavaScript code is first of all entirely dependent on the XSL files and
  249. the ressources should be calculated on the server.
  250. TODO: The JS support in this module should be replaced by independent XSL
  251. files usage and a server-side ressources extraction.
  252. */
  253. function writeJSComplement()
  254. {
  255. $txt = <<<EOT
  256. var _SP_actionMap = [];
  257. function SP_actionMap(vMap)
  258. {
  259. var v = null; for (v in vMap) {
  260. if (!_SP_actionMap[v]) continue;
  261. var oLink = document.getElementById(_SP_actionMap[v] + '_LINK');
  262. var oText = document.getElementById(_SP_actionMap[v] + '_TEXT');
  263. oLink.href = vMap[v]['href'];
  264. oLink.target = vMap[v]['target'] ?
  265. vMap[v]['target'] : '';
  266. oText.innerHTML = vMap[v]['text'] ?
  267. vMap[v]['text'] : 'Ressource locale.';
  268. delete _SP_actionMap[v];
  269. }
  270. }
  271. function _SP_requestRessourceAvailability(sRessource, sId)
  272. {
  273. if (!sRessource || !sId) return;
  274. if (typeof(SP_actionMapURL) == 'undefined') return;
  275. _SP_actionMap[sRessource] = sId;
  276. document.write('<scr' + 'ipt src="' +
  277. SP_actionMapURL.replace("SP_RESSOURCE", sRessource) + '"></scr' + 'ipt>');
  278. }
  279. EOT;
  280. echo $txt;
  281. }
  282. function writeJSOutput(& $sOutput, $aExtraParams = NULL)
  283. {
  284. $sExtraParams = '?';
  285. if (!is_null($aExtraParams)) foreach ($aExtraParams as $k => $v)
  286. $sExtraParams .= "&$k=".urlencode($v);
  287. //$stmp=addcslashes($sOutput, "\"");
  288. $stmp=addcslashes($sOutput, "\n\r\"");
  289. $stmp1=substr($sExtraParams, 1);
  290. $uri=eregi_replace('(xml=[a-z0-9\.]+)','',TZR_COMARQUAGE_PAGE);
  291. $uri=eregi_replace('(xsl=[a-z0-9\.]+)','',$uri);
  292. $stmp=str_replace("%%REFERER%%",$uri.$sExtraParams,$stmp);
  293. //$stmp=str_replace("?xml=","&xml=",$stmp);
  294. // $stmp=str_replace("?&","?",$stmp);
  295. // $stmp=str_replace("??","?",$stmp);
  296. echo "document.write(\"$stmp\");";
  297. }
  298. /* Get call parameters from the current URL and output the compiled XML file
  299. as JavaScript code.
  300. */
  301. function runJavaScript($bContain = TRUE)
  302. {
  303. if ($bContain && !$this->isContained()) {
  304. $this->aParams['handle_not_contained'] and
  305. $this->_handleNotContained();
  306. return FALSE;
  307. }
  308. $aCallParams =& $this->splitCallParams($_GET);
  309. $sOutput =& $this->compileOnePage($aCallParams['call']);
  310. if (!is_string($sOutput)) {
  311. if ($sOutput == -20) {
  312. $sError = "<b>La page ne peut ętre affichée car le contenu XML n'est ".
  313. "pas disponible.<br>Le serveur XML du Service Public pourrait ętre ".
  314. "momentanément hors ligne.</b><br><br>Veuillez réessayer ".
  315. "ultérieurement.";
  316. } else {
  317. $sError = "<b>Une erreur interne s'est produite lors de la génération ".
  318. "de cette page.<br>Les administrateurs ont été notifiés et le ".
  319. "problčme sera résolu sous peu.</b><br><br>Veuillez réessayer ".
  320. "ultérieurement.";
  321. }
  322. $sError = sprintf(implode('',
  323. (array)$this->aParams['html_error_template']), $sError);
  324. $this->writeJSOutput($sError);
  325. return FALSE;
  326. }
  327. $this->writeJSComplement(); echo "\n";
  328. $this->writeJSOutput($sOutput, $aCallParams['rest']);
  329. return TRUE;
  330. }
  331. function & splitCallParams($aValues)
  332. {
  333. $aSplit = array(
  334. 'call' => array(),
  335. 'rest' => array()
  336. );
  337. foreach ($this->_aCallKeys as $k) {
  338. if (!array_key_exists($k, $aValues)) continue;
  339. $aSplit['call'][$k] = $aValues[$k];
  340. unset($aValues[$k]);
  341. }
  342. $aSplit['rest'] = $aValues;
  343. return $aSplit;
  344. }
  345. function dirname($sPath, $iDepth = 1)
  346. {
  347. while ($iDepth--) $sPath = dirname($sPath);
  348. return $sPath == '/' ? '' : $sPath;
  349. }
  350. /* Private.
  351. */
  352. var $_sConfigFile = 'sp.config',
  353. $_aCallKeys = array('xml', 'xsl', 'lettre', 'motcle');
  354. function _error($sError, $iType = E_USER_WARNING)
  355. {
  356. /* TODO: Append errors to an error stack that can be used to simulate
  357. exceptions using some other helper methods.
  358. The email address is considered secure by default. Perform some
  359. security checks first. */
  360. if (!is_null($this->aParams['error_email'])) {
  361. ob_start(); echo "\$_SERVER: "; print_r($_SERVER);
  362. echo "\n\$this: "; print_r($this); $sDump =& ob_get_clean();
  363. $aErrorTypes = array(
  364. E_USER_NOTICE => 'User Notice',
  365. E_USER_WARNING => 'User Warning',
  366. E_USER_ERROR => 'User Error'
  367. );
  368. $sMessage = $aErrorTypes[$iType].': '.$sError."\n\n".$sDump;
  369. mail($this->aParams['error_email'], '[SP] ERROR Notification',
  370. $sMessage, 'From: "'.$_SERVER['HTTP_HOST'].'" <'.
  371. $this->aParams['error_email'].'>', '-f'.
  372. $this->aParams['error_email']);
  373. }
  374. /* TODO: Use a backtrace to gather more info on the error and search for a
  375. possibly derived class when reporting the environement.
  376. */
  377. trigger_error('[ServicePublic] '.$sError, $iType);
  378. }
  379. function _mergeConfigFrom($vConfig)
  380. {
  381. /* A directory or a file name. */
  382. if (is_string($vConfig)) {
  383. if (is_dir($vConfig))
  384. $vConfig .= (substr($vConfig, -1) == '/' ? '' : '/').
  385. $this->_sConfigFile;
  386. if (!file_exists($vConfig)) return TRUE;
  387. $aConfig = parse_ini_file($vConfig);
  388. if (!is_array($aConfig)) {
  389. $this->_error("une erreur s'est produite lors de la lecture du ".
  390. "fichier de configuration <b>$vConfig</b>");
  391. return FALSE;
  392. }
  393. /* Fall through as an array. */
  394. $vConfig =& $aConfig;
  395. }
  396. if (is_array($vConfig)) {
  397. $aKeys = array_intersect(
  398. array_keys($this->aParams), array_keys($vConfig));
  399. if (count($aKeys) != count($vConfig)) {
  400. $this->_error("les options de configuration suivantes n'ont pas été ".
  401. "reconnues : <b>".implode(', ', array_diff(array_keys($vConfig), $aKeys)).
  402. "</b>; ceci n'est pas une erreur fatale mais la configuration de ce ".
  403. "module devrait ętre corrigée", E_USER_NOTICE);
  404. return FALSE;
  405. }
  406. foreach ($aKeys as $k)
  407. $this->aParams[$k] = $vConfig[$k];
  408. }
  409. return TRUE;
  410. }
  411. function _handleNotContained()
  412. {
  413. $txt = <<<EOT
  414. alert("Le module Service Public que vous ętes en train d'appeler\nest protégé \
  415. et ne peut ętre utilisé qu'ŕ l'intérieur d'une application\nqui se trouve sur \
  416. le męme serveur que la page qui l'intčgre.\n\nSi vous pensez qu'il s'agit \
  417. d'une erreur, veuillez signaler\nce problčme aux administrateurs du portail \
  418. que vous ętes\nen train de visiter ou directement aux développeurs ŕ l'adresse \
  419. :\n\nhttp://sourceforge.net/projects/comarquage/.");
  420. EOT;
  421. echo $txt;
  422. }
  423. /* Perform some security checks on the raw call parameters and prepare the
  424. call array for secure use inside the object.
  425. */
  426. function _secureCallParams(& $aCallParams)
  427. {
  428. foreach (array('xml') as $k) {
  429. if (empty($aCallParams[$k]) ||
  430. (($aCallParams[$k] = trim($aCallParams[$k])) &&
  431. !fnmatch('*.'.$k, $aCallParams[$k], FNM_PATHNAME | FNM_PERIOD))) {
  432. $aCallParams[$k] =
  433. $this->aParams['default_'.$k.'_file'];
  434. }
  435. @mkdir(TZR_COMARQUAGE_CACHE_DIR.$k,0777,true);
  436. $aCallParams[$k.'_full_path'] = TZR_COMARQUAGE_CACHE_DIR.$k.'/'.$aCallParams[$k];
  437. $aCallParams['xsl_full_path'] = $this->aParams['root_path'].'/xsl/'.getXSLFile($aCallParams[$k]);
  438. }
  439. }
  440. /* Calculate the cache parameters based on a secure call array.
  441. */
  442. function _prepareCacheParams(& $aCallParams)
  443. {
  444. $sCacheId = '';
  445. !empty($aCallParams['lettre']) and $sCacheId .= 'l'.$aCallParams['lettre'];
  446. !empty($aCallParams['motcle']) and $sCacheId .= 'm'.md5($aCallParams['motcle']);
  447. $aCallParams['cache_full_path'] = TZR_COMARQUAGE_CACHE_DIR.basename($aCallParams['xml'], '.xml').
  448. ($sCacheId ? '.'.$sCacheId : '').'.cache';
  449. }
  450. /*function & _getCache($aCallParams)
  451. {
  452. $sCF = $aCallParams['cache_full_path'];
  453. if (file_exists($sCF) &&
  454. filemtime($sCF) > filemtime($aCallParams['xml_full_path']) &&
  455. filemtime($sCF) > filemtime(dirname($aCallParams['xsl_full_path']))) {
  456. return implode('', file($sCF));
  457. }
  458. return FALSE;
  459. }*/
  460. function & _getCache($aCallParams)
  461. {
  462. $sCF = $aCallParams['cache_full_path'];
  463. if (file_exists($sCF)) {
  464. // Scanne les dates de modification de tous les XSL
  465. if ($handle = opendir(dirname($aCallParams['xsl_full_path']))) {
  466. while (false !== ($file = readdir($handle))) {
  467. if (filemtime($sCF) < filemtime(dirname($aCallParams['xsl_full_path']).'/'.$file)) {
  468. closedir($handle);
  469. return false;
  470. }
  471. }
  472. closedir($handle);
  473. }
  474. if (filemtime($sCF) > filemtime($aCallParams['xml_full_path']) &&
  475. filemtime($sCF) > filemtime(dirname($aCallParams['xsl_full_path']))) {
  476. return implode('', file($sCF));
  477. }
  478. }
  479. return FALSE;
  480. }
  481. function _setCache($aCallParams, & $sOutput)
  482. {
  483. if (!$fp = fopen($aCallParams['cache_full_path'], 'wb')) {
  484. $this->_error("impossible d'écrire dans le fichier ".
  485. "<b>$aCallParams[cache_full_path]</b>");
  486. return FALSE;
  487. }
  488. fwrite($fp, $sOutput);
  489. fclose($fp);
  490. return TRUE;
  491. }
  492. /* Static.
  493. */
  494. static function isMain($sSource = __FILE__)
  495. {
  496. return true;
  497. $fname=str_replace('/restricted-ssh','',$_SERVER['SCRIPT_FILENAME']);
  498. $sSource=eregi_replace('([a-z]+.php)','modsp.php',$sSource);
  499. $res= !empty($fname) && ($fname == $sSource);
  500. return $res;
  501. }
  502. }
  503. class _ServicePublic_XSL_Engine
  504. {
  505. var $oSP = NULL;
  506. function __construct(& $oSP, & $bRet)
  507. {
  508. $this->oSP =& $oSP;
  509. /* TODO: Don't call this more than once per page request. */
  510. $bRet = $this->_isEngineAvailable();
  511. }
  512. /* xsltproc specific.
  513. */
  514. function & transformXMLFile($sXMLFile, $sXSLFile = NULL, $aParams = NULL)
  515. {
  516. $sParams = ' ';
  517. if (!is_null($aParams)) foreach ($aParams as $k => $v) {
  518. if($k != 'PIVOTS') $sParams .= '--stringparam '.escapeshellarg($k).' '.escapeshellarg($v).' ';
  519. }
  520. $sErrorFile = tempnam('/tmp', 'xsltprocErrors_');
  521. $sCommand = $this->_executable.$sParams.($sXSLFile ? $sXSLFile.' ' : '').
  522. "$sXMLFile 2> $sErrorFile";
  523. exec($sCommand, $aRet, $iRet);
  524. if (/*true || */filesize($sErrorFile)) {
  525. $this->oSP->_error("la commande <b>$sCommand</b> a retourné ".
  526. "(<b>$iRet</b>) : ".implode('', file($sErrorFile)));
  527. }
  528. //unlink($sErrorFile);
  529. return $iRet ? FALSE : $aRet;
  530. }
  531. var $_executable = 'xsltproc';
  532. function _isEngineAvailable()
  533. {
  534. foreach (explode(':', getenv('PATH')) as $sPath) {
  535. if (is_executable($sPath.'/'.$this->_executable)) return TRUE;
  536. }
  537. $this->oSP->_error("l'exécutable <b>$this->_executable</b> n'a pas été ".
  538. "trouvé dans le PATH ('<b>".getenv('PATH')."</b>')");
  539. return FALSE;
  540. }
  541. }
  542. function getXSLFile($sXMLFile)
  543. {
  544. $aSheets = array('F' => 'spFichePrincipale.xsl', 'M' => 'spMotsCles.xsl',
  545. 'N' => 'spNoeud.xsl', 'R' => 'spRessource.xsl', 'T' => 'spThemes.xsl');
  546. $sXMLFile=(basename($sXMLFile));
  547. if (!($sXMLFile = trim($sXMLFile))) return FALSE;
  548. if (empty($aSheets[$sXMLFile{0}])) return FALSE;
  549. return $aSheets[$sXMLFile{0}];
  550. }
  551. /* This module can be called directly in which case it uses the local config
  552. file and performs the default JS actions, suited for a basic and rapid
  553. installation.
  554. */
  555. if (ServicePublic_V2::isMain()) {
  556. $oSP =& new ServicePublic_V2();
  557. $oSP->runJavaScript();
  558. }
  559. ?>