PageRenderTime 47ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/core/lib/admin.lib.php

https://github.com/asterix14/dolibarr
PHP | 945 lines | 629 code | 114 blank | 202 comment | 161 complexity | 457838abe12e31a8b3ba20cb9241a316 MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2005-2011 Regis Houssin <regis@dolibarr.fr>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * or see http://www.gnu.org/
  18. */
  19. /**
  20. * \file htdocs/core/lib/admin.lib.php
  21. * \brief Library of admin functions
  22. */
  23. /**
  24. * Renvoi une version en chaine depuis une version en tableau
  25. *
  26. * @param array $versionarray Tableau de version (vermajeur,vermineur,autre)
  27. * @return string Chaine version
  28. */
  29. function versiontostring($versionarray)
  30. {
  31. $string='?';
  32. if (isset($versionarray[0])) $string=$versionarray[0];
  33. if (isset($versionarray[1])) $string.='.'.$versionarray[1];
  34. if (isset($versionarray[2])) $string.='.'.$versionarray[2];
  35. return $string;
  36. }
  37. /**
  38. * Compare 2 versions (stored into 2 arrays)
  39. *
  40. * @param array $versionarray1 Array of version (vermajor,verminor,patch)
  41. * @param array $versionarray2 Array of version (vermajor,verminor,patch)
  42. * @return int -4,-3,-2,-1 if versionarray1<versionarray2 (value depends on level of difference)
  43. * 0 if same
  44. * 1,2,3,4 if versionarray1>versionarray2 (value depends on level of difference)
  45. */
  46. function versioncompare($versionarray1,$versionarray2)
  47. {
  48. $ret=0;
  49. $level=0;
  50. $count1=count($versionarray1);
  51. $count2=count($versionarray2);
  52. $maxcount=max($count1,$count2);
  53. while ($level < $maxcount)
  54. {
  55. $operande1=isset($versionarray1[$level])?$versionarray1[$level]:0;
  56. $operande2=isset($versionarray2[$level])?$versionarray2[$level]:0;
  57. if (preg_match('/alpha|dev/i',$operande1)) $operande1=-3;
  58. if (preg_match('/alpha|dev/i',$operande2)) $operande2=-3;
  59. if (preg_match('/beta/i',$operande1)) $operande1=-2;
  60. if (preg_match('/beta/i',$operande2)) $operande2=-2;
  61. if (preg_match('/rc/i',$operande1)) $operande1=-1;
  62. if (preg_match('/rc/i',$operande2)) $operande2=-1;
  63. $level++;
  64. //print 'level '.$level.' '.$operande1.'-'.$operande2.'<br>';
  65. if ($operande1 < $operande2) { $ret = -$level; break; }
  66. if ($operande1 > $operande2) { $ret = $level; break; }
  67. }
  68. //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret;
  69. return $ret;
  70. }
  71. /**
  72. * Return version PHP
  73. *
  74. * @return array Tableau de version (vermajeur,vermineur,autre)
  75. */
  76. function versionphparray()
  77. {
  78. return explode('.',PHP_VERSION);
  79. }
  80. /**
  81. * Return version Dolibarr
  82. *
  83. * @return array Tableau de version (vermajeur,vermineur,autre)
  84. */
  85. function versiondolibarrarray()
  86. {
  87. return explode('.',DOL_VERSION);
  88. }
  89. /**
  90. * Launch a sql file. Function used by:
  91. * - Migrate process (dolibarr-xyz-abc.sql)
  92. * - Loading sql menus (auguria)
  93. * - Running specific Sql by a module init
  94. * Install process however does not use it.
  95. * Note that Sql files must have all comments at start of line.
  96. *
  97. * @param string $sqlfile Full path to sql file
  98. * @param int $silent 1=Do not output anything, 0=Output line for update page
  99. * @param int $entity Entity targeted for multicompany module
  100. * @param int $usesavepoint 1=Run a savepoint before each request and a rollback to savepoint if error (this allow to have some request with errors inside global transactions).
  101. * @param string $handler Handler targeted for menu
  102. * @return int <=0 if KO, >0 if OK
  103. */
  104. function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='')
  105. {
  106. global $db, $conf, $langs, $user;
  107. dol_syslog("Admin.lib::run_sql run sql file ".$sqlfile, LOG_DEBUG);
  108. $ok=0;
  109. $error=0;
  110. $i=0;
  111. $buffer = '';
  112. $arraysql = Array();
  113. // Get version of database
  114. $versionarray=$db->getVersionArray();
  115. $fp = fopen($sqlfile,"r");
  116. if ($fp)
  117. {
  118. while (! feof($fp))
  119. {
  120. $buf = fgets($fp, 4096);
  121. // Cas special de lignes autorisees pour certaines versions uniquement
  122. if (preg_match('/^--\sV([0-9\.]+)/i',$buf,$reg))
  123. {
  124. $versioncommande=explode('.',$reg[1]);
  125. //print var_dump($versioncommande);
  126. //print var_dump($versionarray);
  127. if (count($versioncommande) && count($versionarray)
  128. && versioncompare($versioncommande,$versionarray) <= 0)
  129. {
  130. // Version qualified, delete SQL comments
  131. $buf=preg_replace('/^--\sV([0-9\.]+)/i','',$buf);
  132. //print "Ligne $i qualifi?e par version: ".$buf.'<br>';
  133. }
  134. }
  135. // Add line buf to buffer if not a comment
  136. if (! preg_match('/^--/',$buf))
  137. {
  138. $buf=preg_replace('/--.*$/','',$buf); //remove comment from a line that not start with -- before add it to the buffer
  139. $buffer .= trim($buf);
  140. }
  141. // print $buf.'<br>';
  142. if (preg_match('/;/',$buffer)) // If string contains ';', it's end of a request string, we save it in arraysql.
  143. {
  144. // Found new request
  145. if ($buffer) $arraysql[$i]=$buffer;
  146. $i++;
  147. $buffer='';
  148. }
  149. }
  150. if ($buffer) $arraysql[$i]=$buffer;
  151. fclose($fp);
  152. }
  153. else
  154. {
  155. dol_syslog("Admin.lib::run_sql failed to open file ".$sqlfile, LOG_ERR);
  156. }
  157. // Loop on each request to see if there is a __+MAX_table__ key
  158. $listofmaxrowid=array(); // This is a cache table
  159. foreach($arraysql as $i => $sql)
  160. {
  161. $newsql=$sql;
  162. // Replace __+MAX_table__ with max of table
  163. while (preg_match('/__\+MAX_([A-Za-z_]+)__/i',$newsql,$reg))
  164. {
  165. $table=$reg[1];
  166. if (! isset($listofmaxrowid[$table]))
  167. {
  168. //var_dump($db);
  169. $sqlgetrowid='SELECT MAX(rowid) as max from '.$table;
  170. $resql=$db->query($sqlgetrowid);
  171. if ($resql)
  172. {
  173. $obj=$db->fetch_object($resql);
  174. $listofmaxrowid[$table]=$obj->max;
  175. if (empty($listofmaxrowid[$table])) $listofmaxrowid[$table]=0;
  176. }
  177. else
  178. {
  179. dol_syslog('Admin.lib::run_sql Failed to get max rowid for '.$table.' '.$db->lasterror().' sql='.$sqlgetrowid, LOG_ERR);
  180. if (! $silent) print '<tr><td valign="top" colspan="2">';
  181. if (! $silent) print '<div class="error">'.$langs->trans("Failed to get max rowid for ".$table)."</div></td>";
  182. if (! $silent) print '</tr>';
  183. $error++;
  184. break;
  185. }
  186. }
  187. $from='__+MAX_'.$table.'__';
  188. $to='+'.$listofmaxrowid[$table];
  189. $newsql=str_replace($from,$to,$newsql);
  190. dol_syslog('Admin.lib::run_sql New Request '.($i+1).' (replacing '.$from.' to '.$to.') sql='.$newsql, LOG_DEBUG);
  191. $arraysql[$i]=$newsql;
  192. }
  193. }
  194. // Loop on each request to execute request
  195. $cursorinsert=0;
  196. $listofinsertedrowid=array();
  197. foreach($arraysql as $i => $sql)
  198. {
  199. if ($sql)
  200. {
  201. if (!empty($handler)) $sql=preg_replace('/__HANDLER__/i',"'".$handler."'",$sql);
  202. $newsql=preg_replace('/__ENTITY__/i',(!empty($entity)?$entity:$conf->entity),$sql);
  203. // Ajout trace sur requete (eventuellement a commenter si beaucoup de requetes)
  204. if (! $silent) print '<tr><td valign="top">'.$langs->trans("Request").' '.($i+1)." sql='".$newsql."'</td></tr>\n";
  205. dol_syslog('Admin.lib::run_sql Request '.($i+1).' sql='.$newsql, LOG_DEBUG);
  206. // Replace for encrypt data
  207. if (preg_match_all('/__ENCRYPT\(\'([^\,]+)\'\)__/i',$newsql,$reg))
  208. {
  209. $num=count($reg[0]);
  210. for($i=0;$i<$num;$i++)
  211. {
  212. $from = $reg[0][$i];
  213. $to = $db->encrypt($reg[1][$i],1);
  214. $newsql = str_replace($from,$to,$newsql);
  215. }
  216. }
  217. // Replace for decrypt data
  218. if (preg_match_all('/__DECRYPT\(\'([^\,]+)\'\)__/i',$newsql,$reg))
  219. {
  220. $num=count($reg[0]);
  221. for($i=0;$i<$num;$i++)
  222. {
  223. $from = $reg[0][$i];
  224. $to = $db->decrypt($reg[1][$i]);
  225. $newsql = str_replace($from,$to,$newsql);
  226. }
  227. }
  228. // Replace __x__ with rowid of insert nb x
  229. while (preg_match('/__([0-9]+)__/',$newsql,$reg))
  230. {
  231. $cursor=$reg[1];
  232. if (empty($listofinsertedrowid[$cursor]))
  233. {
  234. if (! $silent) print '<tr><td valign="top" colspan="2">';
  235. if (! $silent) print '<div class="error">'.$langs->trans("FileIsNotCorrect")."</div></td>";
  236. if (! $silent) print '</tr>';
  237. $error++;
  238. break;
  239. }
  240. $from='__'.$cursor.'__';
  241. $to=$listofinsertedrowid[$cursor];
  242. $newsql=str_replace($from,$to,$newsql);
  243. dol_syslog('Admin.lib::run_sql New Request '.($i+1).' (replacing '.$from.' to '.$to.') sql='.$newsql, LOG_DEBUG);
  244. }
  245. $result=$db->query($newsql,$usesavepoint);
  246. if ($result)
  247. {
  248. if (! $silent) print '<!-- Result = OK -->'."\n";
  249. if (preg_replace('/insert into ([^\s]+)/i',$newsql,$reg))
  250. {
  251. $cursorinsert++;
  252. // It's an insert
  253. $table=preg_replace('/([^a-zA-Z_]+)/i','',$reg[1]);
  254. $insertedrowid=$db->last_insert_id($table);
  255. $listofinsertedrowid[$cursorinsert]=$insertedrowid;
  256. dol_syslog('Admin.lib::run_sql Insert nb '.$cursorinsert.', done in table '.$table.', rowid is '.$listofinsertedrowid[$cursorinsert], LOG_DEBUG);
  257. }
  258. // print '<td align="right">OK</td>';
  259. }
  260. else
  261. {
  262. $errno=$db->errno();
  263. if (! $silent) print '<!-- Result = '.$errno.' -->'."\n";
  264. $okerror=array( 'DB_ERROR_TABLE_ALREADY_EXISTS',
  265. 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  266. 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  267. 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS', // PgSql use same code for table and key already exist
  268. 'DB_ERROR_RECORD_ALREADY_EXISTS',
  269. 'DB_ERROR_NOSUCHTABLE',
  270. 'DB_ERROR_NOSUCHFIELD',
  271. 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
  272. 'DB_ERROR_NO_INDEX_TO_DROP',
  273. 'DB_ERROR_CANNOT_CREATE', // Qd contrainte deja existante
  274. 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
  275. 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS'
  276. );
  277. if (in_array($errno,$okerror))
  278. {
  279. //if (! $silent) print $langs->trans("OK");
  280. }
  281. else
  282. {
  283. if (! $silent) print '<tr><td valign="top" colspan="2">';
  284. if (! $silent) print '<div class="error">'.$langs->trans("Error")." ".$db->errno().": ".$newsql."<br>".$db->error()."</div></td>";
  285. if (! $silent) print '</tr>'."\n";
  286. dol_syslog('Admin.lib::run_sql Request '.($i+1)." Error ".$db->errno()." ".$newsql."<br>".$db->error(), LOG_ERR);
  287. $error++;
  288. }
  289. }
  290. if (! $silent) print '</tr>'."\n";
  291. }
  292. }
  293. if ($error == 0)
  294. {
  295. if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
  296. if (! $silent) print '<td align="right">'.$langs->trans("OK").'</td></tr>'."\n";
  297. $ok = 1;
  298. }
  299. else
  300. {
  301. if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
  302. if (! $silent) print '<td align="right"><font class="error">'.$langs->trans("KO").'</font></td></tr>'."\n";
  303. $ok = 0;
  304. }
  305. return $ok;
  306. }
  307. /**
  308. * Effacement d'une constante dans la base de donnees
  309. *
  310. * @param DoliDB $db Database handler
  311. * @param string $name Name of constant or rowid of line
  312. * @param int $entity Multi company id, -1 for all entities
  313. * @return int <0 if KO, >0 if OK
  314. *
  315. * @see dolibarr_get_const, dolibarr_sel_const
  316. */
  317. function dolibarr_del_const($db, $name, $entity=1)
  318. {
  319. global $conf;
  320. $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
  321. $sql.= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'";
  322. if (is_numeric($name)) $sql.= " OR rowid = '".$db->escape($name)."'";
  323. $sql.= ")";
  324. if ($entity >= 0) $sql.= " AND entity = ".$entity;
  325. dol_syslog("admin.lib::dolibarr_del_const sql=".$sql);
  326. $resql=$db->query($sql);
  327. if ($resql)
  328. {
  329. $conf->global->$name='';
  330. return 1;
  331. }
  332. else
  333. {
  334. dol_print_error($db);
  335. return -1;
  336. }
  337. }
  338. /**
  339. * Recupere une constante depuis la base de donnees.
  340. *
  341. * @param DoliDB $db Database handler
  342. * @param string $name Nom de la constante
  343. * @param int $entity Multi company id
  344. * @return string Valeur de la constante
  345. *
  346. * @see dolibarr_del_const, dolibarr_set_const
  347. */
  348. function dolibarr_get_const($db, $name, $entity=1)
  349. {
  350. global $conf;
  351. $value='';
  352. $sql = "SELECT ".$db->decrypt('value')." as value";
  353. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  354. $sql.= " WHERE name = ".$db->encrypt($name,1);
  355. $sql.= " AND entity = ".$entity;
  356. dol_syslog("admin.lib::dolibarr_get_const sql=".$sql);
  357. $resql=$db->query($sql);
  358. if ($resql)
  359. {
  360. $obj=$db->fetch_object($resql);
  361. if ($obj) $value=$obj->value;
  362. }
  363. return $value;
  364. }
  365. /**
  366. * Insert a parameter (key,value) into database.
  367. *
  368. * @param DoliDB $db Database handler
  369. * @param string $name Name of constant
  370. * @param string $value Value of constant
  371. * @param string $type Type of constante (chaine par defaut)
  372. * @param int $visible Is constant visible in Setup->Other page (0 by default)
  373. * @param string $note Note on parameter
  374. * @param int $entity Multi company id (0 means all entities)
  375. * @return int -1 if KO, 1 if OK
  376. *
  377. * @see dolibarr_del_const, dolibarr_get_const
  378. */
  379. function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
  380. {
  381. global $conf;
  382. // Clean parameters
  383. $name=trim($name);
  384. // Check parameters
  385. if (empty($name))
  386. {
  387. dol_print_error($db,"Error: Call to function dolibarr_set_const with wrong parameters", LOG_ERR);
  388. exit;
  389. }
  390. //dol_syslog("dolibarr_set_const name=$name, value=$value type=$type, visible=$visible, note=$note entity=$entity");
  391. $db->begin();
  392. $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
  393. $sql.= " WHERE name = ".$db->encrypt($name,1);
  394. if ($entity > 0) $sql.= " AND entity = ".$entity;
  395. dol_syslog("admin.lib::dolibarr_set_const sql=".$sql, LOG_DEBUG);
  396. $resql=$db->query($sql);
  397. if (strcmp($value,'')) // true if different. Must work for $value='0' or $value=0
  398. {
  399. $sql = "INSERT INTO llx_const(name,value,type,visible,note,entity)";
  400. $sql.= " VALUES (";
  401. $sql.= $db->encrypt($name,1);
  402. $sql.= ", ".$db->encrypt($value,1);
  403. $sql.= ",'".$type."',".$visible.",'".$db->escape($note)."',".$entity.")";
  404. //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit;
  405. //print "xx".$db->escape($value);
  406. //print $sql;exit;
  407. dol_syslog("admin.lib::dolibarr_set_const sql=".$sql, LOG_DEBUG);
  408. $resql=$db->query($sql);
  409. }
  410. if ($resql)
  411. {
  412. $db->commit();
  413. $conf->global->$name=$value;
  414. return 1;
  415. }
  416. else
  417. {
  418. $error=$db->lasterror();
  419. dol_syslog("admin.lib::dolibarr_set_const ".$error, LOG_ERR);
  420. $db->rollback();
  421. return -1;
  422. }
  423. }
  424. /**
  425. * Define head array for tabs of security setup pages
  426. *
  427. * @return array Array of head
  428. */
  429. function security_prepare_head()
  430. {
  431. global $langs, $conf, $user;
  432. $h = 0;
  433. $head = array();
  434. $head[$h][0] = DOL_URL_ROOT."/admin/proxy.php";
  435. $head[$h][1] = $langs->trans("ExternalAccess");
  436. $head[$h][2] = 'proxy';
  437. $h++;
  438. $head[$h][0] = DOL_URL_ROOT."/admin/security_other.php";
  439. $head[$h][1] = $langs->trans("Miscellanous");
  440. $head[$h][2] = 'misc';
  441. $h++;
  442. $head[$h][0] = DOL_URL_ROOT."/admin/security.php";
  443. $head[$h][1] = $langs->trans("Passwords");
  444. $head[$h][2] = 'passwords';
  445. $h++;
  446. $head[$h][0] = DOL_URL_ROOT."/admin/events.php";
  447. $head[$h][1] = $langs->trans("Audit");
  448. $head[$h][2] = 'audit';
  449. $h++;
  450. $head[$h][0] = DOL_URL_ROOT."/admin/perms.php";
  451. $head[$h][1] = $langs->trans("DefaultRights");
  452. $head[$h][2] = 'default';
  453. $h++;
  454. return $head;
  455. }
  456. /**
  457. * Return list of session
  458. *
  459. * @return array Array list of sessions
  460. */
  461. function listOfSessions()
  462. {
  463. global $conf;
  464. $arrayofSessions = array();
  465. $sessPath = ini_get("session.save_path").'/';
  466. dol_syslog('admin.lib:listOfSessions sessPath='.$sessPath);
  467. $dh = @opendir(dol_osencode($sessPath));
  468. if ($dh)
  469. {
  470. while(($file = @readdir($dh)) !== false)
  471. {
  472. if (preg_match('/^sess_/i',$file) && $file != "." && $file != "..")
  473. {
  474. $fullpath = $sessPath.$file;
  475. if(! @is_dir($fullpath) && is_readable($fullpath))
  476. {
  477. $sessValues = file_get_contents($fullpath); // get raw session data
  478. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  479. preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i',$sessValues) && // limit to current entity
  480. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  481. {
  482. $tmp=explode('_', $file);
  483. $idsess=$tmp[1];
  484. $login = preg_match('/dol_login\|s:[0-9]+:"([A-Za-z0-9]+)"/i',$sessValues,$regs);
  485. $arrayofSessions[$idsess]["login"] = $regs[1];
  486. $arrayofSessions[$idsess]["age"] = time()-filectime($fullpath);
  487. $arrayofSessions[$idsess]["creation"] = filectime($fullpath);
  488. $arrayofSessions[$idsess]["modification"] = filemtime($fullpath);
  489. $arrayofSessions[$idsess]["raw"] = $sessValues;
  490. }
  491. }
  492. }
  493. }
  494. @closedir($dh);
  495. }
  496. return $arrayofSessions;
  497. }
  498. /**
  499. * Purge existing sessions
  500. *
  501. * @param int $mysessionid To avoid to try to delete my own session
  502. * @return int >0 if OK, <0 if KO
  503. */
  504. function purgeSessions($mysessionid)
  505. {
  506. global $conf;
  507. $arrayofSessions = array();
  508. $sessPath = ini_get("session.save_path")."/";
  509. dol_syslog('admin.lib:purgeSessions mysessionid='.$mysessionid.' sessPath='.$sessPath);
  510. $error=0;
  511. $dh = @opendir(dol_osencode($sessPath));
  512. while(($file = @readdir($dh)) !== false)
  513. {
  514. if ($file != "." && $file != "..")
  515. {
  516. $fullpath = $sessPath.$file;
  517. if(! @is_dir($fullpath))
  518. {
  519. $sessValues = file_get_contents($fullpath); // get raw session data
  520. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  521. preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i',$sessValues) && // limit to current entity
  522. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  523. {
  524. $tmp=explode('_', $file);
  525. $idsess=$tmp[1];
  526. // We remove session if it's not ourself
  527. if ($idsess != $mysessionid)
  528. {
  529. $res=@unlink($fullpath);
  530. if (! $res) $error++;
  531. }
  532. }
  533. }
  534. }
  535. }
  536. @closedir($dh);
  537. if (! $error) return 1;
  538. else return -$error;
  539. }
  540. /**
  541. * Enable a module
  542. *
  543. * @param string $value Name of module to activate
  544. * @param int $withdeps Activate/Disable also all dependencies
  545. * @return string Error message or '';
  546. */
  547. function Activate($value,$withdeps=1)
  548. {
  549. global $db, $modules, $langs, $conf;
  550. // Check parameters
  551. if (empty($value)) return 'ErrorBadParameter';
  552. $ret='';
  553. $modName = $value;
  554. $modFile = $modName . ".class.php";
  555. $modulesdir = array();
  556. // Loop on each directory
  557. $found=false;
  558. foreach ($conf->file->dol_document_root as $type => $dirroot)
  559. {
  560. $modulesdir[] = $dirroot."/core/modules/";
  561. if ($type == 'alt')
  562. {
  563. $handle=@opendir(dol_osencode($dirroot));
  564. if (is_resource($handle))
  565. {
  566. while (($file = readdir($handle))!==false)
  567. {
  568. if (is_dir($dirroot.'/'.$file) && substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS' && $file != 'includes')
  569. {
  570. if (is_dir($dirroot . '/' . $file . '/core/modules/'))
  571. {
  572. $modulesdir[] = $dirroot . '/' . $file . '/core/modules/';
  573. }
  574. }
  575. }
  576. closedir($handle);
  577. }
  578. }
  579. }
  580. foreach ($modulesdir as $dir)
  581. {
  582. if (file_exists($dir.$modFile))
  583. {
  584. $found=@include_once($dir.$modFile);
  585. if ($found) break;
  586. }
  587. }
  588. $objMod = new $modName($db);
  589. // Test if PHP version ok
  590. $verphp=versionphparray();
  591. $vermin=isset($objMod->phpmin)?$objMod->phpmin:0;
  592. if (is_array($vermin) && versioncompare($verphp,$vermin) < 0)
  593. {
  594. return $langs->trans("ErrorModuleRequirePHPVersion",versiontostring($vermin));
  595. }
  596. // Test if Dolibarr version ok
  597. $verdol=versiondolibarrarray();
  598. $vermin=isset($objMod->need_dolibarr_version)?$objMod->need_dolibarr_version:0;
  599. //print 'eee'.versioncompare($verdol,$vermin).join(',',$verdol).' - '.join(',',$vermin);exit;
  600. if (is_array($vermin) && versioncompare($verdol,$vermin) < 0)
  601. {
  602. return $langs->trans("ErrorModuleRequireDolibarrVersion",versiontostring($vermin));
  603. }
  604. // Test if javascript requirement ok
  605. if (! empty($objMod->need_javascript_ajax) && empty($conf->use_javascript_ajax))
  606. {
  607. return $langs->trans("ErrorModuleRequireJavascript");
  608. }
  609. $result=$objMod->init();
  610. if ($result <= 0) $ret=$objMod->error;
  611. if (! $ret && $withdeps)
  612. {
  613. if (is_array($objMod->depends) && !empty($objMod->depends))
  614. {
  615. // Activation des modules dont le module depend
  616. $num = count($objMod->depends);
  617. for ($i = 0; $i < $num; $i++)
  618. {
  619. if (file_exists(DOL_DOCUMENT_ROOT."/core/modules/".$objMod->depends[$i].".class.php"))
  620. {
  621. Activate($objMod->depends[$i]);
  622. }
  623. }
  624. }
  625. if (isset($objMod->conflictwith) && is_array($objMod->conflictwith))
  626. {
  627. // Desactivation des modules qui entrent en conflit
  628. $num = count($objMod->conflictwith);
  629. for ($i = 0; $i < $num; $i++)
  630. {
  631. if (file_exists(DOL_DOCUMENT_ROOT."/core/modules/".$objMod->conflictwith[$i].".class.php"))
  632. {
  633. UnActivate($objMod->conflictwith[$i],0);
  634. }
  635. }
  636. }
  637. }
  638. return $ret;
  639. }
  640. /**
  641. * Disable a module
  642. *
  643. * @param string $value Nom du module a desactiver
  644. * @param int $requiredby 1=Desactive aussi modules dependants
  645. * @return string Error message or '';
  646. */
  647. function UnActivate($value, $requiredby=1)
  648. {
  649. global $db, $modules, $conf;
  650. // Check parameters
  651. if (empty($value)) return 'ErrorBadParameter';
  652. $ret='';
  653. $modName = $value;
  654. $modFile = $modName . ".class.php";
  655. $modulesdir=array();
  656. // Loop on each directory
  657. $found=false;
  658. foreach ($conf->file->dol_document_root as $type => $dirroot)
  659. {
  660. $modulesdir[] = $dirroot."/core/modules/";
  661. if ($type == 'alt')
  662. {
  663. $handle=@opendir(dol_osencode($dirroot));
  664. if (is_resource($handle))
  665. {
  666. while (($file = readdir($handle))!==false)
  667. {
  668. if (is_dir($dirroot.'/'.$file) && substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS' && $file != 'includes')
  669. {
  670. if (is_dir($dirroot . '/' . $file . '/core/modules/'))
  671. {
  672. $modulesdir[] = $dirroot . '/' . $file . '/core/modules/';
  673. }
  674. }
  675. }
  676. closedir($handle);
  677. }
  678. }
  679. }
  680. foreach ($modulesdir as $dir)
  681. {
  682. if (file_exists($dir.$modFile))
  683. {
  684. $found=@include_once($dir.$modFile);
  685. if ($found) break;
  686. }
  687. }
  688. if ($found)
  689. {
  690. $objMod = new $modName($db);
  691. $result=$objMod->remove();
  692. }
  693. else
  694. {
  695. // TODO Cannot instantiate abstract class
  696. //$genericMod = new DolibarrModul($db);
  697. //$genericMod->name=preg_replace('/^mod/i','',$modName);
  698. //$genericMod->style_sheet=1;
  699. //$genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName));
  700. //$genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName));
  701. dol_syslog("modules::UnActivate Failed to find module file, we use generic function with name " . $modName);
  702. //$genericMod->_remove();
  703. }
  704. // Desactivation des modules qui dependent de lui
  705. if ($requiredby)
  706. {
  707. $countrb=count($objMod->requiredby);
  708. for ($i = 0; $i < $countrb; $i++)
  709. {
  710. UnActivate($objMod->requiredby[$i]);
  711. }
  712. }
  713. return $ret;
  714. }
  715. /**
  716. * Add external modules to list of dictionnaries
  717. *
  718. * @param array &$taborder Taborder
  719. * @param array &$tabname Tabname
  720. * @param array &$tablib Tablib
  721. * @param array &$tabsql Tabsql
  722. * @param array &$tabsqlsort Tabsqlsort
  723. * @param array &$tabfield Tabfield
  724. * @param array &$tabfieldvalue Tabfieldvalue
  725. * @param array &$tabfieldinsert Tabfieldinsert
  726. * @param array &$tabrowid Tabrowid
  727. * @param array &$tabcond Tabcond
  728. * @return int 1
  729. */
  730. function complete_dictionnary_with_modules(&$taborder,&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond)
  731. {
  732. global $db, $modules, $conf, $langs;
  733. // Search modules
  734. $filename = array();
  735. $modules = array();
  736. $orders = array();
  737. $categ = array();
  738. $dirmod = array();
  739. $i = 0; // is a sequencer of modules found
  740. $j = 0; // j is module number. Automatically affected if module number not defined.
  741. foreach ($conf->file->dol_document_root as $dirroot)
  742. {
  743. $dir = $dirroot . "/core/modules/";
  744. // Load modules attributes in arrays (name, numero, orders) from dir directory
  745. //print $dir."\n<br>";
  746. dol_syslog("Scan directory ".$dir." for modules");
  747. $handle=@opendir(dol_osencode($dir));
  748. if (is_resource($handle))
  749. {
  750. while (($file = readdir($handle))!==false)
  751. {
  752. //print "$i ".$file."\n<br>";
  753. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  754. {
  755. $modName = substr($file, 0, dol_strlen($file) - 10);
  756. if ($modName)
  757. {
  758. include_once($dir.$file);
  759. $objMod = new $modName($db);
  760. if ($objMod->numero > 0)
  761. {
  762. $j = $objMod->numero;
  763. }
  764. else
  765. {
  766. $j = 1000 + $i;
  767. }
  768. $modulequalified=1;
  769. // We discard modules according to features level (PS: if module is activated we always show it)
  770. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  771. if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
  772. if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
  773. if ($modulequalified)
  774. {
  775. // Load languages files of module
  776. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  777. {
  778. foreach($objMod->langfiles as $langfile)
  779. {
  780. $langs->load($langfile);
  781. }
  782. }
  783. $modules[$i] = $objMod;
  784. $filename[$i]= $modName;
  785. $orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module
  786. //print "x".$modName." ".$orders[$i]."\n<br>";
  787. if (isset($categ[$objMod->special])) $categ[$objMod->special]++; // Array of all different modules categories
  788. else $categ[$objMod->special]=1;
  789. $dirmod[$i] = $dirroot;
  790. // Complete arrays
  791. //&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond
  792. //$objMod
  793. if (! empty($objMod->dictionnaries))
  794. {
  795. //var_dump($objMod->dictionnaries['tabname']);
  796. $taborder[] = 0;
  797. foreach($objMod->dictionnaries['tabname'] as $val)
  798. {
  799. $taborder[] = count($tabname)+1;
  800. $tabname[] = $val;
  801. }
  802. foreach($objMod->dictionnaries['tablib'] as $val) $tablib[] = $val;
  803. foreach($objMod->dictionnaries['tabsql'] as $val) $tabsql[] = $val;
  804. foreach($objMod->dictionnaries['tabsqlsort'] as $val) $tabsqlsort[] = $val;
  805. foreach($objMod->dictionnaries['tabfield'] as $val) $tabfield[] = $val;
  806. foreach($objMod->dictionnaries['tabfieldvalue'] as $val) $tabfieldvalue[] = $val;
  807. foreach($objMod->dictionnaries['tabfieldinsert'] as $val) $tabfieldinsert[] = $val;
  808. foreach($objMod->dictionnaries['tabrowid'] as $val) $tabrowid[] = $val;
  809. foreach($objMod->dictionnaries['tabcond'] as $val) $tabcond[] = $val;
  810. // foreach($objMod->dictionnaries['tabsqlsort'] as $val) $tablib[] = $val;
  811. //$tabname = array_merge ($tabname, $objMod->dictionnaries['tabname']);
  812. //var_dump($tabcond);
  813. //exit;
  814. }
  815. $j++;
  816. $i++;
  817. }
  818. else dol_syslog("Module ".get_class($objMod)." not qualified");
  819. }
  820. }
  821. }
  822. closedir($handle);
  823. }
  824. else
  825. {
  826. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  827. }
  828. }
  829. return 1;
  830. }
  831. ?>