admin.lib.php 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. <?php
  2. /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2005-2016 Regis Houssin <regis.houssin@capnetworks.com>
  4. * Copyright (C) 2012 J. Fernando Lagrange <fernando@demo-tic.org>
  5. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. * or see http://www.gnu.org/
  20. */
  21. /**
  22. * \file htdocs/core/lib/admin.lib.php
  23. * \brief Library of admin functions
  24. */
  25. require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
  26. /**
  27. * Renvoi une version en chaine depuis une version en tableau
  28. *
  29. * @param array $versionarray Tableau de version (vermajeur,vermineur,autre)
  30. * @return string Chaine version
  31. */
  32. function versiontostring($versionarray)
  33. {
  34. $string='?';
  35. if (isset($versionarray[0])) $string=$versionarray[0];
  36. if (isset($versionarray[1])) $string.='.'.$versionarray[1];
  37. if (isset($versionarray[2])) $string.='.'.$versionarray[2];
  38. return $string;
  39. }
  40. /**
  41. * Compare 2 versions (stored into 2 arrays).
  42. * To check if Dolibarr version is lower than (x,y,z), do "if versioncompare(versiondolibarrarray(), array(x.y.z)) <= 0"
  43. * For example: if (versioncompare(versiondolibarrarray(),array(4,0,-4)) >= 0) is true if version is 4.0 alpha or higher.
  44. * For example: if (versioncompare(versiondolibarrarray(),array(4,0,0)) >= 0) is true if version is 4.0 final or higher.
  45. * For example: if (versioncompare(versiondolibarrarray(),array(4,0,1)) >= 0) is true if version is 4.0.1 or higher.
  46. * Alternative way to compare: if ((float) DOL_VERSION >= 4.0) is true if version is 4.0 alpha or higher (works only to compare first and second level)
  47. *
  48. * @param array $versionarray1 Array of version (vermajor,verminor,patch)
  49. * @param array $versionarray2 Array of version (vermajor,verminor,patch)
  50. * @return int -4,-3,-2,-1 if versionarray1<versionarray2 (value depends on level of difference)
  51. * 0 if same
  52. * 1,2,3,4 if versionarray1>versionarray2 (value depends on level of difference)
  53. */
  54. function versioncompare($versionarray1,$versionarray2)
  55. {
  56. $ret=0;
  57. $level=0;
  58. $count1=count($versionarray1);
  59. $count2=count($versionarray2);
  60. $maxcount=max($count1,$count2);
  61. while ($level < $maxcount)
  62. {
  63. $operande1=isset($versionarray1[$level])?$versionarray1[$level]:0;
  64. $operande2=isset($versionarray2[$level])?$versionarray2[$level]:0;
  65. if (preg_match('/alpha|dev/i',$operande1)) $operande1=-5;
  66. if (preg_match('/alpha|dev/i',$operande2)) $operande2=-5;
  67. if (preg_match('/beta$/i',$operande1)) $operande1=-4;
  68. if (preg_match('/beta$/i',$operande2)) $operande2=-4;
  69. if (preg_match('/beta([0-9])+/i',$operande1)) $operande1=-3;
  70. if (preg_match('/beta([0-9])+/i',$operande2)) $operande2=-3;
  71. if (preg_match('/rc$/i',$operande1)) $operande1=-2;
  72. if (preg_match('/rc$/i',$operande2)) $operande2=-2;
  73. if (preg_match('/rc([0-9])+/i',$operande1)) $operande1=-1;
  74. if (preg_match('/rc([0-9])+/i',$operande2)) $operande2=-1;
  75. $level++;
  76. //print 'level '.$level.' '.$operande1.'-'.$operande2.'<br>';
  77. if ($operande1 < $operande2) { $ret = -$level; break; }
  78. if ($operande1 > $operande2) { $ret = $level; break; }
  79. }
  80. //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n";
  81. return $ret;
  82. }
  83. /**
  84. * Return version PHP
  85. *
  86. * @return array Tableau de version (vermajeur,vermineur,autre)
  87. */
  88. function versionphparray()
  89. {
  90. return explode('.',PHP_VERSION);
  91. }
  92. /**
  93. * Return version Dolibarr
  94. *
  95. * @return array Tableau de version (vermajeur,vermineur,autre)
  96. */
  97. function versiondolibarrarray()
  98. {
  99. return explode('.',DOL_VERSION);
  100. }
  101. /**
  102. * Launch a sql file. Function used by:
  103. * - Migrate process (dolibarr-xyz-abc.sql)
  104. * - Loading sql menus (auguria)
  105. * - Running specific Sql by a module init
  106. * Install process however does not use it.
  107. * Note that Sql files must have all comments at start of line.
  108. *
  109. * @param string $sqlfile Full path to sql file
  110. * @param int $silent 1=Do not output anything, 0=Output line for update page
  111. * @param int $entity Entity targeted for multicompany module
  112. * @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).
  113. * @param string $handler Handler targeted for menu
  114. * @param string $okerror Family of errors we accept ('default', 'none')
  115. * @return int <=0 if KO, >0 if OK
  116. */
  117. function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$okerror='default')
  118. {
  119. global $db, $conf, $langs, $user;
  120. dol_syslog("Admin.lib::run_sql run sql file ".$sqlfile." silent=".$silent." entity=".$entity." usesavepoint=".$usesavepoint." handler=".$handler." okerror=".$okerror, LOG_DEBUG);
  121. $ok=0;
  122. $error=0;
  123. $i=0;
  124. $buffer = '';
  125. $arraysql = Array();
  126. // Get version of database
  127. $versionarray=$db->getVersionArray();
  128. $fp = fopen($sqlfile,"r");
  129. if ($fp)
  130. {
  131. while (! feof($fp))
  132. {
  133. $buf = fgets($fp, 4096);
  134. // Test if request must be ran only for particular database or version (if yes, we must remove the -- comment)
  135. if (preg_match('/^--\sV(MYSQL|PGSQL|)([0-9\.]+)/i',$buf,$reg))
  136. {
  137. $qualified=1;
  138. // restrict on database type
  139. if (! empty($reg[1]))
  140. {
  141. if (! preg_match('/'.preg_quote($reg[1]).'/i',$db->type)) $qualified=0;
  142. }
  143. // restrict on version
  144. if ($qualified)
  145. {
  146. $versionrequest=explode('.',$reg[2]);
  147. //print var_dump($versionrequest);
  148. //print var_dump($versionarray);
  149. if (! count($versionrequest) || ! count($versionarray) || versioncompare($versionrequest,$versionarray) > 0)
  150. {
  151. $qualified=0;
  152. }
  153. }
  154. if ($qualified)
  155. {
  156. // Version qualified, delete SQL comments
  157. $buf=preg_replace('/^--\sV(MYSQL|PGSQL|)([0-9\.]+)/i','',$buf);
  158. //print "Ligne $i qualifi?e par version: ".$buf.'<br>';
  159. }
  160. }
  161. // Add line buf to buffer if not a comment
  162. if (! preg_match('/^--/',$buf))
  163. {
  164. $buf=preg_replace('/--.*$/','',$buf); //remove comment from a line that not start with -- before add it to the buffer
  165. $buffer .= trim($buf);
  166. }
  167. // print $buf.'<br>';
  168. if (preg_match('/;/',$buffer)) // If string contains ';', it's end of a request string, we save it in arraysql.
  169. {
  170. // Found new request
  171. if ($buffer) $arraysql[$i]=$buffer;
  172. $i++;
  173. $buffer='';
  174. }
  175. }
  176. if ($buffer) $arraysql[$i]=$buffer;
  177. fclose($fp);
  178. }
  179. else
  180. {
  181. dol_syslog("Admin.lib::run_sql failed to open file ".$sqlfile, LOG_ERR);
  182. }
  183. // Loop on each request to see if there is a __+MAX_table__ key
  184. $listofmaxrowid=array(); // This is a cache table
  185. foreach($arraysql as $i => $sql)
  186. {
  187. $newsql=$sql;
  188. // Replace __+MAX_table__ with max of table
  189. while (preg_match('/__\+MAX_([A-Za-z_]+)__/i',$newsql,$reg))
  190. {
  191. $table=$reg[1];
  192. if (! isset($listofmaxrowid[$table]))
  193. {
  194. //var_dump($db);
  195. $sqlgetrowid='SELECT MAX(rowid) as max from '.$table;
  196. $resql=$db->query($sqlgetrowid);
  197. if ($resql)
  198. {
  199. $obj=$db->fetch_object($resql);
  200. $listofmaxrowid[$table]=$obj->max;
  201. if (empty($listofmaxrowid[$table])) $listofmaxrowid[$table]=0;
  202. }
  203. else
  204. {
  205. if (! $silent) print '<tr><td valign="top" colspan="2">';
  206. if (! $silent) print '<div class="error">'.$langs->trans("Failed to get max rowid for ".$table)."</div></td>";
  207. if (! $silent) print '</tr>';
  208. $error++;
  209. break;
  210. }
  211. }
  212. $from='__+MAX_'.$table.'__';
  213. $to='+'.$listofmaxrowid[$table];
  214. $newsql=str_replace($from,$to,$newsql);
  215. dol_syslog('Admin.lib::run_sql New Request '.($i+1).' (replacing '.$from.' to '.$to.')', LOG_DEBUG);
  216. $arraysql[$i]=$newsql;
  217. }
  218. }
  219. // Loop on each request to execute request
  220. $cursorinsert=0;
  221. $listofinsertedrowid=array();
  222. foreach($arraysql as $i => $sql)
  223. {
  224. if ($sql)
  225. {
  226. // Replace the prefix tables
  227. if (MAIN_DB_PREFIX != 'llx_')
  228. {
  229. $sql=preg_replace('/llx_/i',MAIN_DB_PREFIX,$sql);
  230. }
  231. if (!empty($handler)) $sql=preg_replace('/__HANDLER__/i',"'".$handler."'",$sql);
  232. $newsql=preg_replace('/__ENTITY__/i',(!empty($entity)?$entity:$conf->entity),$sql);
  233. // Ajout trace sur requete (eventuellement a commenter si beaucoup de requetes)
  234. if (! $silent) print '<tr><td class="tdtop">'.$langs->trans("Request").' '.($i+1)." sql='".dol_htmlentities($newsql,ENT_NOQUOTES)."'</td></tr>\n";
  235. dol_syslog('Admin.lib::run_sql Request '.($i+1), LOG_DEBUG);
  236. $sqlmodified=0;
  237. // Replace for encrypt data
  238. if (preg_match_all('/__ENCRYPT\(\'([^\']+)\'\)__/i',$newsql,$reg))
  239. {
  240. $num=count($reg[0]);
  241. for($j=0;$j<$num;$j++)
  242. {
  243. $from = $reg[0][$j];
  244. $to = $db->encrypt($reg[1][$j],1);
  245. $newsql = str_replace($from,$to,$newsql);
  246. }
  247. $sqlmodified++;
  248. }
  249. // Replace for decrypt data
  250. if (preg_match_all('/__DECRYPT\(\'([A-Za-z0-9_]+)\'\)__/i',$newsql,$reg))
  251. {
  252. $num=count($reg[0]);
  253. for($j=0;$j<$num;$j++)
  254. {
  255. $from = $reg[0][$j];
  256. $to = $db->decrypt($reg[1][$j]);
  257. $newsql = str_replace($from,$to,$newsql);
  258. }
  259. $sqlmodified++;
  260. }
  261. // Replace __x__ with rowid of insert nb x
  262. while (preg_match('/__([0-9]+)__/',$newsql,$reg))
  263. {
  264. $cursor=$reg[1];
  265. if (empty($listofinsertedrowid[$cursor]))
  266. {
  267. if (! $silent) print '<tr><td valign="top" colspan="2">';
  268. if (! $silent) print '<div class="error">'.$langs->trans("FileIsNotCorrect")."</div></td>";
  269. if (! $silent) print '</tr>';
  270. $error++;
  271. break;
  272. }
  273. $from='__'.$cursor.'__';
  274. $to=$listofinsertedrowid[$cursor];
  275. $newsql=str_replace($from,$to,$newsql);
  276. $sqlmodified++;
  277. }
  278. if ($sqlmodified) dol_syslog('Admin.lib::run_sql New Request '.($i+1), LOG_DEBUG);
  279. $result=$db->query($newsql,$usesavepoint);
  280. if ($result)
  281. {
  282. if (! $silent) print '<!-- Result = OK -->'."\n";
  283. if (preg_replace('/insert into ([^\s]+)/i',$newsql,$reg))
  284. {
  285. $cursorinsert++;
  286. // It's an insert
  287. $table=preg_replace('/([^a-zA-Z_]+)/i','',$reg[1]);
  288. $insertedrowid=$db->last_insert_id($table);
  289. $listofinsertedrowid[$cursorinsert]=$insertedrowid;
  290. dol_syslog('Admin.lib::run_sql Insert nb '.$cursorinsert.', done in table '.$table.', rowid is '.$listofinsertedrowid[$cursorinsert], LOG_DEBUG);
  291. }
  292. // print '<td align="right">OK</td>';
  293. }
  294. else
  295. {
  296. $errno=$db->errno();
  297. if (! $silent) print '<!-- Result = '.$errno.' -->'."\n";
  298. // Define list of errors we accept (array $okerrors)
  299. $okerrors=array( // By default
  300. 'DB_ERROR_TABLE_ALREADY_EXISTS',
  301. 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  302. 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  303. 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS', // PgSql use same code for table and key already exist
  304. 'DB_ERROR_RECORD_ALREADY_EXISTS',
  305. 'DB_ERROR_NOSUCHTABLE',
  306. 'DB_ERROR_NOSUCHFIELD',
  307. 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
  308. 'DB_ERROR_NO_INDEX_TO_DROP',
  309. 'DB_ERROR_CANNOT_CREATE', // Qd contrainte deja existante
  310. 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
  311. 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
  312. 'DB_ERROR_22P02'
  313. );
  314. if ($okerror == 'none') $okerrors=array();
  315. // Is it an error we accept
  316. if (! in_array($errno,$okerrors))
  317. {
  318. if (! $silent) print '<tr><td valign="top" colspan="2">';
  319. if (! $silent) print '<div class="error">'.$langs->trans("Error")." ".$db->errno().": ".$newsql."<br>".$db->error()."</div></td>";
  320. if (! $silent) print '</tr>'."\n";
  321. dol_syslog('Admin.lib::run_sql Request '.($i+1)." Error ".$db->errno()." ".$newsql."<br>".$db->error(), LOG_ERR);
  322. $error++;
  323. }
  324. }
  325. if (! $silent) print '</tr>'."\n";
  326. }
  327. }
  328. if ($error == 0)
  329. {
  330. if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
  331. if (! $silent) print '<td align="right">'.$langs->trans("OK").'</td></tr>'."\n";
  332. $ok = 1;
  333. }
  334. else
  335. {
  336. if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
  337. if (! $silent) print '<td align="right"><font class="error">'.$langs->trans("KO").'</font></td></tr>'."\n";
  338. $ok = 0;
  339. }
  340. return $ok;
  341. }
  342. /**
  343. * Effacement d'une constante dans la base de donnees
  344. *
  345. * @param DoliDB $db Database handler
  346. * @param string $name Name of constant or rowid of line
  347. * @param int $entity Multi company id, -1 for all entities
  348. * @return int <0 if KO, >0 if OK
  349. *
  350. * @see dolibarr_get_const, dolibarr_set_const, dol_set_user_param
  351. */
  352. function dolibarr_del_const($db, $name, $entity=1)
  353. {
  354. global $conf;
  355. if (empty($name))
  356. {
  357. dol_print_error('','Error call dolibar_del_const with parameter name empty');
  358. return -1;
  359. }
  360. $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
  361. $sql.= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'";
  362. if (is_numeric($name)) $sql.= " OR rowid = '".$db->escape($name)."'";
  363. $sql.= ")";
  364. if ($entity >= 0) $sql.= " AND entity = ".$entity;
  365. dol_syslog("admin.lib::dolibarr_del_const", LOG_DEBUG);
  366. $resql=$db->query($sql);
  367. if ($resql)
  368. {
  369. $conf->global->$name='';
  370. return 1;
  371. }
  372. else
  373. {
  374. dol_print_error($db);
  375. return -1;
  376. }
  377. }
  378. /**
  379. * Recupere une constante depuis la base de donnees.
  380. *
  381. * @param DoliDB $db Database handler
  382. * @param string $name Nom de la constante
  383. * @param int $entity Multi company id
  384. * @return string Valeur de la constante
  385. *
  386. * @see dolibarr_del_const, dolibarr_set_const, dol_set_user_param
  387. */
  388. function dolibarr_get_const($db, $name, $entity=1)
  389. {
  390. global $conf;
  391. $value='';
  392. $sql = "SELECT ".$db->decrypt('value')." as value";
  393. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  394. $sql.= " WHERE name = ".$db->encrypt($name,1);
  395. $sql.= " AND entity = ".$entity;
  396. dol_syslog("admin.lib::dolibarr_get_const", LOG_DEBUG);
  397. $resql=$db->query($sql);
  398. if ($resql)
  399. {
  400. $obj=$db->fetch_object($resql);
  401. if ($obj) $value=$obj->value;
  402. }
  403. return $value;
  404. }
  405. /**
  406. * Insert a parameter (key,value) into database (delete old key then insert it again).
  407. *
  408. * @param DoliDB $db Database handler
  409. * @param string $name Name of constant
  410. * @param string $value Value of constant
  411. * @param string $type Type of constante (chaine par defaut)
  412. * @param int $visible Is constant visible in Setup->Other page (0 by default)
  413. * @param string $note Note on parameter
  414. * @param int $entity Multi company id (0 means all entities)
  415. * @return int -1 if KO, 1 if OK
  416. *
  417. * @see dolibarr_del_const, dolibarr_get_const, dol_set_user_param
  418. */
  419. function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
  420. {
  421. global $conf;
  422. // Clean parameters
  423. $name=trim($name);
  424. // Check parameters
  425. if (empty($name))
  426. {
  427. dol_print_error($db,"Error: Call to function dolibarr_set_const with wrong parameters", LOG_ERR);
  428. exit;
  429. }
  430. //dol_syslog("dolibarr_set_const name=$name, value=$value type=$type, visible=$visible, note=$note entity=$entity");
  431. $db->begin();
  432. $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
  433. $sql.= " WHERE name = ".$db->encrypt($name,1);
  434. if ($entity >= 0) $sql.= " AND entity = ".$entity;
  435. dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG);
  436. $resql=$db->query($sql);
  437. if (strcmp($value,'')) // true if different. Must work for $value='0' or $value=0
  438. {
  439. $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity)";
  440. $sql.= " VALUES (";
  441. $sql.= $db->encrypt($name,1);
  442. $sql.= ", ".$db->encrypt($value,1);
  443. $sql.= ",'".$type."',".$visible.",'".$db->escape($note)."',".$entity.")";
  444. //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit;
  445. //print "xx".$db->escape($value);
  446. dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG);
  447. $resql=$db->query($sql);
  448. }
  449. if ($resql)
  450. {
  451. $db->commit();
  452. $conf->global->$name=$value;
  453. return 1;
  454. }
  455. else
  456. {
  457. $error=$db->lasterror();
  458. $db->rollback();
  459. return -1;
  460. }
  461. }
  462. /**
  463. * Prepare array with list of tabs
  464. *
  465. * @return array Array of tabs to show
  466. */
  467. function security_prepare_head()
  468. {
  469. global $langs, $conf, $user;
  470. $h = 0;
  471. $head = array();
  472. $head[$h][0] = DOL_URL_ROOT."/admin/security_other.php";
  473. $head[$h][1] = $langs->trans("Miscellaneous");
  474. $head[$h][2] = 'misc';
  475. $h++;
  476. $head[$h][0] = DOL_URL_ROOT."/admin/security.php";
  477. $head[$h][1] = $langs->trans("Passwords");
  478. $head[$h][2] = 'passwords';
  479. $h++;
  480. $head[$h][0] = DOL_URL_ROOT."/admin/security_file.php";
  481. $head[$h][1] = $langs->trans("Files");
  482. $head[$h][2] = 'file';
  483. $h++;
  484. $head[$h][0] = DOL_URL_ROOT."/admin/proxy.php";
  485. $head[$h][1] = $langs->trans("ExternalAccess");
  486. $head[$h][2] = 'proxy';
  487. $h++;
  488. $head[$h][0] = DOL_URL_ROOT."/admin/events.php";
  489. $head[$h][1] = $langs->trans("Audit");
  490. $head[$h][2] = 'audit';
  491. $h++;
  492. $head[$h][0] = DOL_URL_ROOT."/admin/perms.php";
  493. $head[$h][1] = $langs->trans("DefaultRights");
  494. $head[$h][2] = 'default';
  495. $h++;
  496. return $head;
  497. }
  498. /**
  499. * Prepare array with list of tabs
  500. *
  501. * @return array Array of tabs to show
  502. */
  503. function translation_prepare_head()
  504. {
  505. global $langs, $conf, $user;
  506. $h = 0;
  507. $head = array();
  508. $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=overwrite";
  509. $head[$h][1] = $langs->trans("TranslationOverwriteKey");
  510. $head[$h][2] = 'overwrite';
  511. $h++;
  512. $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey";
  513. $head[$h][1] = $langs->trans("TranslationKeySearch");
  514. $head[$h][2] = 'searchkey';
  515. $h++;
  516. complete_head_from_modules($conf,$langs,null,$head,$h,'translation_admin');
  517. complete_head_from_modules($conf,$langs,null,$head,$h,'translation_admin','remove');
  518. return $head;
  519. }
  520. /**
  521. * Prepare array with list of tabs
  522. *
  523. * @return array Array of tabs to show
  524. */
  525. function defaultvalues_prepare_head()
  526. {
  527. global $langs, $conf, $user;
  528. $h = 0;
  529. $head = array();
  530. $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=createform";
  531. $head[$h][1] = $langs->trans("DefaultCreateForm");
  532. $head[$h][2] = 'createform';
  533. $h++;
  534. $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=filters";
  535. $head[$h][1] = $langs->trans("DefaultSearchFilters");
  536. $head[$h][2] = 'filters';
  537. $h++;
  538. $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=sortorder";
  539. $head[$h][1] = $langs->trans("DefaultSortOrder");
  540. $head[$h][2] = 'sortorder';
  541. $h++;
  542. $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=focus";
  543. $head[$h][1] = $langs->trans("DefaultFocus");
  544. $head[$h][2] = 'focus';
  545. $h++;
  546. /*$head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey";
  547. $head[$h][1] = $langs->trans("TranslationKeySearch");
  548. $head[$h][2] = 'searchkey';
  549. $h++;*/
  550. complete_head_from_modules($conf,$langs,null,$head,$h,'defaultvalues_admin');
  551. complete_head_from_modules($conf,$langs,null,$head,$h,'defaultvalues_admin','remove');
  552. return $head;
  553. }
  554. /**
  555. * Return list of session
  556. *
  557. * @return array Array list of sessions
  558. */
  559. function listOfSessions()
  560. {
  561. global $conf;
  562. $arrayofSessions = array();
  563. // session.save_path can be returned empty so we set a default location and work from there
  564. $sessPath = '/tmp';
  565. $iniPath = ini_get("session.save_path");
  566. if ($iniPath) {
  567. $sessPath = $iniPath;
  568. }
  569. $sessPath .= '/'; // We need the trailing slash
  570. dol_syslog('admin.lib:listOfSessions sessPath='.$sessPath);
  571. $dh = @opendir(dol_osencode($sessPath));
  572. if ($dh)
  573. {
  574. while(($file = @readdir($dh)) !== false)
  575. {
  576. if (preg_match('/^sess_/i',$file) && $file != "." && $file != "..")
  577. {
  578. $fullpath = $sessPath.$file;
  579. if(! @is_dir($fullpath) && is_readable($fullpath))
  580. {
  581. $sessValues = file_get_contents($fullpath); // get raw session data
  582. // Example of possible value
  583. //$sessValues = 'newtoken|s:32:"1239f7a0c4b899200fe9ca5ea394f307";dol_loginmesg|s:0:"";newtoken|s:32:"1236457104f7ae0f328c2928973f3cb5";dol_loginmesg|s:0:"";token|s:32:"123615ad8d650c5cc4199b9a1a76783f";dol_login|s:5:"admin";dol_authmode|s:8:"dolibarr";dol_tz|s:1:"1";dol_tz_string|s:13:"Europe/Berlin";dol_dst|i:0;dol_dst_observed|s:1:"1";dol_dst_first|s:0:"";dol_dst_second|s:0:"";dol_screenwidth|s:4:"1920";dol_screenheight|s:3:"971";dol_company|s:12:"MyBigCompany";dol_entity|i:1;mainmenu|s:4:"home";leftmenuopened|s:10:"admintools";idmenu|s:0:"";leftmenu|s:10:"admintools";';
  584. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  585. (preg_match('/dol_entity\|i:'.$conf->entity.';/i',$sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i',$sessValues)) && // limit to current entity
  586. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  587. {
  588. $tmp=explode('_', $file);
  589. $idsess=$tmp[1];
  590. $login = preg_match('/dol_login\|s:[0-9]+:"([A-Za-z0-9]+)"/i',$sessValues,$regs);
  591. $arrayofSessions[$idsess]["login"] = $regs[1];
  592. $arrayofSessions[$idsess]["age"] = time()-filectime($fullpath);
  593. $arrayofSessions[$idsess]["creation"] = filectime($fullpath);
  594. $arrayofSessions[$idsess]["modification"] = filemtime($fullpath);
  595. $arrayofSessions[$idsess]["raw"] = $sessValues;
  596. }
  597. }
  598. }
  599. }
  600. @closedir($dh);
  601. }
  602. return $arrayofSessions;
  603. }
  604. /**
  605. * Purge existing sessions
  606. *
  607. * @param int $mysessionid To avoid to try to delete my own session
  608. * @return int >0 if OK, <0 if KO
  609. */
  610. function purgeSessions($mysessionid)
  611. {
  612. global $conf;
  613. $arrayofSessions = array();
  614. $sessPath = ini_get("session.save_path")."/";
  615. dol_syslog('admin.lib:purgeSessions mysessionid='.$mysessionid.' sessPath='.$sessPath);
  616. $error=0;
  617. $dh = @opendir(dol_osencode($sessPath));
  618. while(($file = @readdir($dh)) !== false)
  619. {
  620. if ($file != "." && $file != "..")
  621. {
  622. $fullpath = $sessPath.$file;
  623. if(! @is_dir($fullpath))
  624. {
  625. $sessValues = file_get_contents($fullpath); // get raw session data
  626. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  627. preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i',$sessValues) && // limit to current entity
  628. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  629. {
  630. $tmp=explode('_', $file);
  631. $idsess=$tmp[1];
  632. // We remove session if it's not ourself
  633. if ($idsess != $mysessionid)
  634. {
  635. $res=@unlink($fullpath);
  636. if (! $res) $error++;
  637. }
  638. }
  639. }
  640. }
  641. }
  642. @closedir($dh);
  643. if (! $error) return 1;
  644. else return -$error;
  645. }
  646. /**
  647. * Enable a module
  648. *
  649. * @param string $value Name of module to activate
  650. * @param int $withdeps Activate/Disable also all dependencies
  651. * @return array array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added);
  652. */
  653. function activateModule($value,$withdeps=1)
  654. {
  655. global $db, $modules, $langs, $conf;
  656. // Check parameters
  657. if (empty($value)) {
  658. $ret['errors'][] = 'ErrorBadParameter';
  659. return $ret;
  660. }
  661. $ret=array('nbmodules'=>0, 'errors'=>array(), 'nbperms'=>0);
  662. $modName = $value;
  663. $modFile = $modName . ".class.php";
  664. // Loop on each directory to fill $modulesdir
  665. $modulesdir = dolGetModulesDirs();
  666. // Loop on each modulesdir directories
  667. $found=false;
  668. foreach ($modulesdir as $dir)
  669. {
  670. if (file_exists($dir.$modFile))
  671. {
  672. $found=@include_once $dir.$modFile;
  673. if ($found) break;
  674. }
  675. }
  676. $objMod = new $modName($db);
  677. // Test if PHP version ok
  678. $verphp=versionphparray();
  679. $vermin=isset($objMod->phpmin)?$objMod->phpmin:0;
  680. if (is_array($vermin) && versioncompare($verphp, $vermin) < 0) {
  681. $ret['errors'][] = $langs->trans("ErrorModuleRequirePHPVersion", versiontostring($vermin));
  682. return $ret;
  683. }
  684. // Test if Dolibarr version ok
  685. $verdol=versiondolibarrarray();
  686. $vermin=isset($objMod->need_dolibarr_version)?$objMod->need_dolibarr_version:0;
  687. //print 'eee '.versioncompare($verdol,$vermin).' - '.join(',',$verdol).' - '.join(',',$vermin);exit;
  688. if (is_array($vermin) && versioncompare($verdol, $vermin) < 0) {
  689. $ret['errors'][] = $langs->trans("ErrorModuleRequireDolibarrVersion", versiontostring($vermin));
  690. return $ret;
  691. }
  692. // Test if javascript requirement ok
  693. if (!empty($objMod->need_javascript_ajax) && empty($conf->use_javascript_ajax)) {
  694. $ret['errors'][] = $langs->trans("ErrorModuleRequireJavascript");
  695. return $ret;
  696. }
  697. $const_name = $objMod->const_name;
  698. if(!empty($conf->global->$const_name)){
  699. return $ret;
  700. }
  701. $result=$objMod->init(); // Enable module
  702. if ($result <= 0)
  703. {
  704. $ret['errors'][]=$objMod->error;
  705. }
  706. else
  707. {
  708. if ($withdeps)
  709. {
  710. if (isset($objMod->depends) && is_array($objMod->depends) && ! empty($objMod->depends))
  711. {
  712. // Activation of modules this module depends on
  713. // this->depends may be array('modModule1', 'mmodModule2') or array('always'=>"modModule1", 'FR'=>'modModule2')
  714. foreach ($objMod->depend as $key => $modulestring)
  715. {
  716. if ((! is_numeric($key)) && $key != 'always' && $key != $mysoc->country_code)
  717. {
  718. dol_syslog("We are not concerned by dependency with key=".$key." because our country is ".$mysoc->country_code);
  719. continue;
  720. }
  721. $activate = false;
  722. foreach ($modulesdir as $dir)
  723. {
  724. if (file_exists($dir.$modulestring.".class.php"))
  725. {
  726. $resarray = activateModule($modulestring);
  727. if (empty($resarray['errors'])){
  728. $activate = true;
  729. }else{
  730. foreach ($resarray['errors'] as $errorMessage){
  731. dol_syslog($errorMessage, LOG_ERR);
  732. }
  733. }
  734. break;
  735. }
  736. }
  737. if ($activate)
  738. {
  739. $ret['nbmodules']+=$resarray['nbmodules'];
  740. $ret['nbperms']+=$resarray['nbperms'];
  741. }
  742. else
  743. {
  744. $ret['errors'][] = $langs->trans('activateModuleDependNotSatisfied', $objMod->name, $modulestring);
  745. }
  746. }
  747. }
  748. if (isset($objMod->conflictwith) && is_array($objMod->conflictwith) && ! empty($objMod->conflictwith))
  749. {
  750. // Desactivation des modules qui entrent en conflit
  751. $num = count($objMod->conflictwith);
  752. for ($i = 0; $i < $num; $i++)
  753. {
  754. foreach ($modulesdir as $dir)
  755. {
  756. if (file_exists($dir.$objMod->conflictwith[$i].".class.php"))
  757. {
  758. unActivateModule($objMod->conflictwith[$i],0);
  759. }
  760. }
  761. }
  762. }
  763. }
  764. }
  765. if (! count($ret['errors']))
  766. {
  767. $ret['nbmodules']++;
  768. $ret['nbperms']+=count($objMod->rights);
  769. }
  770. return $ret;
  771. }
  772. /**
  773. * Disable a module
  774. *
  775. * @param string $value Nom du module a desactiver
  776. * @param int $requiredby 1=Desactive aussi modules dependants
  777. * @return string Error message or '';
  778. */
  779. function unActivateModule($value, $requiredby=1)
  780. {
  781. global $db, $modules, $conf;
  782. // Check parameters
  783. if (empty($value)) return 'ErrorBadParameter';
  784. $ret='';
  785. $modName = $value;
  786. $modFile = $modName . ".class.php";
  787. // Loop on each directory to fill $modulesdir
  788. $modulesdir = dolGetModulesDirs();
  789. // Loop on each modulesdir directories
  790. $found=false;
  791. foreach ($modulesdir as $dir)
  792. {
  793. if (file_exists($dir.$modFile))
  794. {
  795. $found=@include_once $dir.$modFile;
  796. if ($found) break;
  797. }
  798. }
  799. if ($found)
  800. {
  801. $objMod = new $modName($db);
  802. $result=$objMod->remove();
  803. if ($result <= 0) $ret=$objMod->error;
  804. }
  805. else
  806. {
  807. //print $dir.$modFile;
  808. // TODO Replace this after DolibarrModules is moved as abstract class with a try catch to show module we try to disable has not been found or could not be loaded
  809. $genericMod = new DolibarrModules($db);
  810. $genericMod->name=preg_replace('/^mod/i','',$modName);
  811. $genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName));
  812. $genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName));
  813. dol_syslog("modules::unActivateModule Failed to find module file, we use generic function with name " . $modName);
  814. $genericMod->_remove(array());
  815. }
  816. // Desactivation des modules qui dependent de lui
  817. if (! $ret && $requiredby)
  818. {
  819. $countrb=count($objMod->requiredby);
  820. for ($i = 0; $i < $countrb; $i++)
  821. {
  822. //var_dump($objMod->requiredby[$i]);
  823. unActivateModule($objMod->requiredby[$i]);
  824. }
  825. }
  826. return $ret;
  827. }
  828. /**
  829. * Add external modules to list of dictionaries
  830. *
  831. * @param array $taborder Taborder
  832. * @param array $tabname Tabname
  833. * @param array $tablib Tablib
  834. * @param array $tabsql Tabsql
  835. * @param array $tabsqlsort Tabsqlsort
  836. * @param array $tabfield Tabfield
  837. * @param array $tabfieldvalue Tabfieldvalue
  838. * @param array $tabfieldinsert Tabfieldinsert
  839. * @param array $tabrowid Tabrowid
  840. * @param array $tabcond Tabcond
  841. * @param array $tabhelp Tabhelp
  842. * @param array $tabfieldcheck Tabfieldcheck
  843. * @return int 1
  844. */
  845. function complete_dictionary_with_modules(&$taborder,&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond,&$tabhelp,&$tabfieldcheck)
  846. {
  847. global $db, $modules, $conf, $langs;
  848. // Search modules
  849. $modulesdir = dolGetModulesDirs();
  850. $i = 0; // is a sequencer of modules found
  851. $j = 0; // j is module number. Automatically affected if module number not defined.
  852. foreach ($modulesdir as $dir)
  853. {
  854. // Load modules attributes in arrays (name, numero, orders) from dir directory
  855. //print $dir."\n<br>";
  856. dol_syslog("Scan directory ".$dir." for modules");
  857. $handle=@opendir(dol_osencode($dir));
  858. if (is_resource($handle))
  859. {
  860. while (($file = readdir($handle))!==false)
  861. {
  862. //print "$i ".$file."\n<br>";
  863. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  864. {
  865. $modName = substr($file, 0, dol_strlen($file) - 10);
  866. if ($modName)
  867. {
  868. include_once $dir.$file;
  869. $objMod = new $modName($db);
  870. if ($objMod->numero > 0)
  871. {
  872. $j = $objMod->numero;
  873. }
  874. else
  875. {
  876. $j = 1000 + $i;
  877. }
  878. $modulequalified=1;
  879. // We discard modules according to features level (PS: if module is activated we always show it)
  880. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  881. if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
  882. if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
  883. //If module is not activated disqualified
  884. if (empty($conf->global->$const_name)) $modulequalified=0;
  885. if ($modulequalified)
  886. {
  887. // Load languages files of module
  888. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  889. {
  890. foreach($objMod->langfiles as $langfile)
  891. {
  892. $langs->load($langfile);
  893. }
  894. }
  895. // Complete arrays
  896. //&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond
  897. if (empty($objMod->dictionaries) && ! empty($objMod->dictionnaries)) $objMod->dictionaries=$objMod->dictionnaries; // For backward compatibility
  898. if (! empty($objMod->dictionaries))
  899. {
  900. //var_dump($objMod->dictionaries['tabname']);
  901. $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp=0;
  902. foreach($objMod->dictionaries['tabname'] as $val) { $nbtabname++; $taborder[] = max($taborder)+1; $tabname[] = $val; }
  903. foreach($objMod->dictionaries['tablib'] as $val) { $nbtablib++; $tablib[] = $val; }
  904. foreach($objMod->dictionaries['tabsql'] as $val) { $nbtabsql++; $tabsql[] = $val; }
  905. foreach($objMod->dictionaries['tabsqlsort'] as $val) { $nbtabsqlsort++; $tabsqlsort[] = $val; }
  906. foreach($objMod->dictionaries['tabfield'] as $val) { $nbtabfield++; $tabfield[] = $val; }
  907. foreach($objMod->dictionaries['tabfieldvalue'] as $val) { $nbtabfieldvalue++; $tabfieldvalue[] = $val; }
  908. foreach($objMod->dictionaries['tabfieldinsert'] as $val) { $nbtabfieldinsert++; $tabfieldinsert[] = $val; }
  909. foreach($objMod->dictionaries['tabrowid'] as $val) { $nbtabrowid++; $tabrowid[] = $val; }
  910. foreach($objMod->dictionaries['tabcond'] as $val) { $nbtabcond++; $tabcond[] = $val; }
  911. if (! empty($objMod->dictionaries['tabhelp'])) foreach($objMod->dictionaries['tabhelp'] as $val) { $nbtabhelp++; $tabhelp[] = $val; }
  912. if (! empty($objMod->dictionaries['tabfieldcheck'])) foreach($objMod->dictionaries['tabfieldcheck'] as $val) { $nbtabfieldcheck++; $tabfieldcheck[] = $val; }
  913. if ($nbtabname != $nbtablib || $nbtablib != $nbtabsql || $nbtabsql != $nbtabsqlsort)
  914. {
  915. print 'Error in descriptor of module '.$const_name.'. Array ->dictionaries has not same number of record for key "tabname", "tablib", "tabsql" and "tabsqlsort"';
  916. //print "$const_name: $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp\n";
  917. }
  918. }
  919. $j++;
  920. $i++;
  921. }
  922. else dol_syslog("Module ".get_class($objMod)." not qualified");
  923. }
  924. }
  925. }
  926. closedir($handle);
  927. }
  928. else
  929. {
  930. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  931. }
  932. }
  933. return 1;
  934. }
  935. /**
  936. * Add external modules to list of contact element
  937. *
  938. * @param array $elementList elementList
  939. * @return int 1
  940. */
  941. function complete_elementList_with_modules(&$elementList)
  942. {
  943. global $db, $modules, $conf, $langs;
  944. // Search modules
  945. $filename = array();
  946. $modules = array();
  947. $orders = array();
  948. $categ = array();
  949. $dirmod = array();
  950. $i = 0; // is a sequencer of modules found
  951. $j = 0; // j is module number. Automatically affected if module number not defined.
  952. $modulesdir = dolGetModulesDirs();
  953. foreach ($modulesdir as $dir)
  954. {
  955. // Load modules attributes in arrays (name, numero, orders) from dir directory
  956. //print $dir."\n<br>";
  957. dol_syslog("Scan directory ".$dir." for modules");
  958. $handle=@opendir(dol_osencode($dir));
  959. if (is_resource($handle))
  960. {
  961. while (($file = readdir($handle))!==false)
  962. {
  963. //print "$i ".$file."\n<br>";
  964. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  965. {
  966. $modName = substr($file, 0, dol_strlen($file) - 10);
  967. if ($modName)
  968. {
  969. include_once $dir.$file;
  970. $objMod = new $modName($db);
  971. if ($objMod->numero > 0)
  972. {
  973. $j = $objMod->numero;
  974. }
  975. else
  976. {
  977. $j = 1000 + $i;
  978. }
  979. $modulequalified=1;
  980. // We discard modules according to features level (PS: if module is activated we always show it)
  981. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  982. if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
  983. if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
  984. //If module is not activated disqualified
  985. if (empty($conf->global->$const_name)) $modulequalified=0;
  986. if ($modulequalified)
  987. {
  988. // Load languages files of module
  989. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  990. {
  991. foreach($objMod->langfiles as $langfile)
  992. {
  993. $langs->load($langfile);
  994. }
  995. }
  996. $modules[$i] = $objMod;
  997. $filename[$i]= $modName;
  998. $orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module
  999. //print "x".$modName." ".$orders[$i]."\n<br>";
  1000. if (isset($categ[$objMod->special])) $categ[$objMod->special]++; // Array of all different modules categories
  1001. else $categ[$objMod->special]=1;
  1002. $dirmod[$i] = $dirroot;
  1003. if (! empty($objMod->module_parts['contactelement']))
  1004. {
  1005. $elementList[$objMod->name] = $langs->trans($objMod->name);
  1006. }
  1007. $j++;
  1008. $i++;
  1009. }
  1010. else dol_syslog("Module ".get_class($objMod)." not qualified");
  1011. }
  1012. }
  1013. }
  1014. closedir($handle);
  1015. }
  1016. else
  1017. {
  1018. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  1019. }
  1020. }
  1021. return 1;
  1022. }
  1023. /**
  1024. * Show array with constants to edit
  1025. *
  1026. * @param array $tableau Array of constants
  1027. * @param int $strictw3c 0=Include form into table (deprecated), 1=Form is outside table to respect W3C (no form into table), 2=No form nor button at all
  1028. * @param string $helptext Help
  1029. * @return void
  1030. */
  1031. function form_constantes($tableau, $strictw3c=0, $helptext='')
  1032. {
  1033. global $db,$bc,$langs,$conf,$_Avery_Labels;
  1034. $form = new Form($db);
  1035. if (! empty($strictw3c) && $strictw3c == 1) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  1036. print '<table class="noborder" width="100%">';
  1037. print '<tr class="liste_titre">';
  1038. print '<td>'.$langs->trans("Description").'</td>';
  1039. print '<td>';
  1040. $text = $langs->trans("Value");
  1041. print $form->textwithpicto($text, $helptext, 1, 'help', '', 0, 2, 'idhelptext');
  1042. print '</td>';
  1043. if (empty($strictw3c)) print '<td align="center" width="80">'.$langs->trans("Action").'</td>';
  1044. print "</tr>\n";
  1045. $var=true;
  1046. $listofparam=array();
  1047. foreach($tableau as $const) // Loop on each param
  1048. {
  1049. $sql = "SELECT ";
  1050. $sql.= "rowid";
  1051. $sql.= ", ".$db->decrypt('name')." as name";
  1052. $sql.= ", ".$db->decrypt('value')." as value";
  1053. $sql.= ", type";
  1054. $sql.= ", note";
  1055. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  1056. $sql.= " WHERE ".$db->decrypt('name')." = '".$const."'";
  1057. $sql.= " AND entity IN (0, ".$conf->entity.")";
  1058. $sql.= " ORDER BY name ASC, entity DESC";
  1059. $result = $db->query($sql);
  1060. dol_syslog("List params", LOG_DEBUG);
  1061. if ($result)
  1062. {
  1063. $obj = $db->fetch_object($result); // Take first result of select
  1064. // For avoid warning in strict mode
  1065. if (empty($obj)) {
  1066. $obj = (object) array('rowid'=>'','name'=>'','value'=>'','type'=>'','note'=>'');
  1067. }
  1068. if (empty($strictw3c)) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  1069. print '<tr class="oddeven">';
  1070. // Show constant
  1071. print '<td>';
  1072. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  1073. print '<input type="hidden" name="action" value="update">';
  1074. print '<input type="hidden" name="rowid'.(empty($strictw3c)?'':'[]').'" value="'.$obj->rowid.'">';
  1075. print '<input type="hidden" name="constname'.(empty($strictw3c)?'':'[]').'" value="'.$const.'">';
  1076. print '<input type="hidden" name="constnote'.(empty($strictw3c)?'':'[]').'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">';
  1077. print $langs->trans('Desc'.$const);
  1078. if ($const == 'ADHERENT_MAILMAN_URL')
  1079. {
  1080. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick1">'.img_down().'</a><br>';
  1081. //print 'http://lists.exampe.com/cgi-bin/mailman/admin/%LISTE%/members?adminpw=%MAILMAN_ADMINPW%&subscribees=%EMAIL%&send_welcome_msg_to_this_batch=1';
  1082. print '<div id="example1" class="hidden">';
  1083. print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/add?subscribees_upload=%EMAIL%&amp;adminpw=%MAILMAN_ADMINPW%&amp;subscribe_or_invite=0&amp;send_welcome_msg_to_this_batch=0&amp;notification_to_list_owner=0';
  1084. print '</div>';
  1085. }
  1086. if ($const == 'ADHERENT_MAILMAN_UNSUB_URL')
  1087. {
  1088. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick2">'.img_down().'</a><br>';
  1089. print '<div id="example2" class="hidden">';
  1090. print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?unsubscribees_upload=%EMAIL%&amp;adminpw=%MAILMAN_ADMINPW%&amp;send_unsub_ack_to_this_batch=0&amp;send_unsub_notifications_to_list_owner=0';
  1091. print '</div>';
  1092. //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
  1093. }
  1094. if ($const == 'ADHERENT_MAILMAN_LISTS')
  1095. {
  1096. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick3">'.img_down().'</a><br>';
  1097. print '<div id="example3" class="hidden">';
  1098. print 'mymailmanlist<br>';
  1099. print 'mymailmanlist1,mymailmanlist2<br>';
  1100. print 'TYPE:Type1:mymailmanlist1,TYPE:Type2:mymailmanlist2<br>';
  1101. if ($conf->categorie->enabled) print 'CATEG:Categ1:mymailmanlist1,CATEG:Categ2:mymailmanlist2<br>';
  1102. print '</div>';
  1103. //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
  1104. }
  1105. print "</td>\n";
  1106. // Value
  1107. if ($const == 'ADHERENT_CARD_TYPE' || $const == 'ADHERENT_ETIQUETTE_TYPE')
  1108. {
  1109. print '<td>';
  1110. // List of possible labels (defined into $_Avery_Labels variable set into format_cards.lib.php)
  1111. require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
  1112. $arrayoflabels=array();
  1113. foreach(array_keys($_Avery_Labels) as $codecards)
  1114. {
  1115. $arrayoflabels[$codecards]=$_Avery_Labels[$codecards]['name'];
  1116. }
  1117. print $form->selectarray('constvalue'.(empty($strictw3c)?'':'[]'),$arrayoflabels,($obj->value?$obj->value:'CARD'),1,0,0);
  1118. print '<input type="hidden" name="consttype" value="yesno">';
  1119. print '</td>';
  1120. }
  1121. else
  1122. {
  1123. print '<td>';
  1124. if (in_array($const,array('ADHERENT_CARD_TEXT','ADHERENT_CARD_TEXT_RIGHT','ADHERENT_ETIQUETTE_TEXT')))
  1125. {
  1126. print '<textarea class="flat" name="constvalue'.(empty($strictw3c)?'':'[]').'" cols="50" rows="5" wrap="soft">'."\n";
  1127. print $obj->value;
  1128. print "</textarea>\n";
  1129. print '<input type="hidden" name="consttype" value="texte">';
  1130. }
  1131. else if (in_array($const,array('ADHERENT_AUTOREGISTER_NOTIF_MAIL','ADHERENT_AUTOREGISTER_MAIL','ADHERENT_MAIL_VALID','ADHERENT_MAIL_COTIS','ADHERENT_MAIL_RESIL')))
  1132. {
  1133. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  1134. $doleditor=new DolEditor('constvalue_'.$const.(empty($strictw3c)?'':'[]'),$obj->value,'',160,'dolibarr_notes','',false,false,$conf->fckeditor->enabled,ROWS_5,'90%');
  1135. $doleditor->Create();
  1136. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="texte">';
  1137. }
  1138. else if ($obj->type == 'yesno')
  1139. {
  1140. print $form->selectyesno('constvalue'.(empty($strictw3c)?'':'[]'),$obj->value,1);
  1141. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="yesno">';
  1142. }
  1143. else
  1144. {
  1145. print '<input type="text" class="flat" size="48" name="constvalue'.(empty($strictw3c)?'':'[]').'" value="'.dol_escape_htmltag($obj->value).'">';
  1146. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="chaine">';
  1147. }
  1148. print '</td>';
  1149. }
  1150. // Submit
  1151. if (empty($strictw3c))
  1152. {
  1153. print '<td align="center">';
  1154. print '<input type="submit" class="button" value="'.$langs->trans("Update").'" name="Button">';
  1155. print "</td>";
  1156. }
  1157. print "</tr>\n";
  1158. if (empty($strictw3c)) print "</form>\n";
  1159. }
  1160. }
  1161. print '</table>';
  1162. if (! empty($strictw3c) && $strictw3c == 1)
  1163. {
  1164. print '<div align="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
  1165. print "</form>\n";
  1166. }
  1167. }
  1168. /**
  1169. * Show array with constants to edit
  1170. *
  1171. * @param array $modules Array of all modules
  1172. * @return string HTML string with warning
  1173. */
  1174. function showModulesExludedForExternal($modules)
  1175. {
  1176. global $conf,$langs;
  1177. $text=$langs->trans("OnlyFollowingModulesAreOpenedToExternalUsers");
  1178. $listofmodules=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL);
  1179. $i=0;
  1180. if (!empty($modules)) {
  1181. foreach($modules as $module)
  1182. {
  1183. $moduleconst=$module->const_name;
  1184. $modulename=strtolower($module->name);
  1185. //print 'modulename='.$modulename;
  1186. //if (empty($conf->global->$moduleconst)) continue;
  1187. if (! in_array($modulename,$listofmodules)) continue;
  1188. //var_dump($modulename.'eee'.$langs->trans('Module'.$module->numero.'Name'));
  1189. if ($i > 0) $text.=', ';
  1190. else $text.=' ';
  1191. $i++;
  1192. $text .= $langs->trans('Module'.$module->numero.'Name');
  1193. }
  1194. }
  1195. return $text;
  1196. }
  1197. /**
  1198. * Add document model used by doc generator
  1199. *
  1200. * @param string $name Model name
  1201. * @param string $type Model type
  1202. * @param string $label Model label
  1203. * @param string $description Model description
  1204. * @return int <0 if KO, >0 if OK
  1205. */
  1206. function addDocumentModel($name, $type, $label='', $description='')
  1207. {
  1208. global $db, $conf;
  1209. $db->begin();
  1210. $sql = "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity, libelle, description)";
  1211. $sql.= " VALUES ('".$db->escape($name)."','".$type."',".$conf->entity.", ";
  1212. $sql.= ($label?"'".$db->escape($label)."'":'null').", ";
  1213. $sql.= (! empty($description)?"'".$db->escape($description)."'":"null");
  1214. $sql.= ")";
  1215. dol_syslog("admin.lib::addDocumentModel", LOG_DEBUG);
  1216. $resql=$db->query($sql);
  1217. if ($resql)
  1218. {
  1219. $db->commit();
  1220. return 1;
  1221. }
  1222. else
  1223. {
  1224. dol_print_error($db);
  1225. $db->rollback();
  1226. return -1;
  1227. }
  1228. }
  1229. /**
  1230. * Delete document model used by doc generator
  1231. *
  1232. * @param string $name Model name
  1233. * @param string $type Model type
  1234. * @return int <0 if KO, >0 if OK
  1235. */
  1236. function delDocumentModel($name, $type)
  1237. {
  1238. global $db, $conf;
  1239. $db->begin();
  1240. $sql = "DELETE FROM ".MAIN_DB_PREFIX."document_model";
  1241. $sql.= " WHERE nom = '".$db->escape($name)."'";
  1242. $sql.= " AND type = '".$type."'";
  1243. $sql.= " AND entity = ".$conf->entity;
  1244. dol_syslog("admin.lib::delDocumentModel", LOG_DEBUG);
  1245. $resql=$db->query($sql);
  1246. if ($resql)
  1247. {
  1248. $db->commit();
  1249. return 1;
  1250. }
  1251. else
  1252. {
  1253. dol_print_error($db);
  1254. $db->rollback();
  1255. return -1;
  1256. }
  1257. }
  1258. /**
  1259. * Return the php_info into an array
  1260. *
  1261. * @return array Array with PHP infos
  1262. */
  1263. function phpinfo_array()
  1264. {
  1265. ob_start();
  1266. phpinfo();
  1267. $info_arr = array();
  1268. $info_lines = explode("\n", strip_tags(ob_get_clean(), "<tr><td><h2>")); // end of ob_start()
  1269. $cat = "General";
  1270. foreach($info_lines as $line)
  1271. {
  1272. // new cat?
  1273. preg_match("~<h2>(.*)</h2>~", $line, $title) ? $cat = $title[1] : null;
  1274. if(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
  1275. {
  1276. $info_arr[trim($cat)][trim($val[1])] = $val[2];
  1277. }
  1278. elseif(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
  1279. {
  1280. $info_arr[trim($cat)][trim($val[1])] = array("local" => $val[2], "master" => $val[3]);
  1281. }
  1282. }
  1283. return $info_arr;
  1284. }