admin.lib.php 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418
  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. * Return list of session
  522. *
  523. * @return array Array list of sessions
  524. */
  525. function listOfSessions()
  526. {
  527. global $conf;
  528. $arrayofSessions = array();
  529. // session.save_path can be returned empty so we set a default location and work from there
  530. $sessPath = '/tmp';
  531. $iniPath = ini_get("session.save_path");
  532. if ($iniPath) {
  533. $sessPath = $iniPath;
  534. }
  535. $sessPath .= '/'; // We need the trailing slash
  536. dol_syslog('admin.lib:listOfSessions sessPath='.$sessPath);
  537. $dh = @opendir(dol_osencode($sessPath));
  538. if ($dh)
  539. {
  540. while(($file = @readdir($dh)) !== false)
  541. {
  542. if (preg_match('/^sess_/i',$file) && $file != "." && $file != "..")
  543. {
  544. $fullpath = $sessPath.$file;
  545. if(! @is_dir($fullpath) && is_readable($fullpath))
  546. {
  547. $sessValues = file_get_contents($fullpath); // get raw session data
  548. // Example of possible value
  549. //$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";';
  550. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  551. (preg_match('/dol_entity\|i:'.$conf->entity.';/i',$sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i',$sessValues)) && // limit to current entity
  552. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  553. {
  554. $tmp=explode('_', $file);
  555. $idsess=$tmp[1];
  556. $login = preg_match('/dol_login\|s:[0-9]+:"([A-Za-z0-9]+)"/i',$sessValues,$regs);
  557. $arrayofSessions[$idsess]["login"] = $regs[1];
  558. $arrayofSessions[$idsess]["age"] = time()-filectime($fullpath);
  559. $arrayofSessions[$idsess]["creation"] = filectime($fullpath);
  560. $arrayofSessions[$idsess]["modification"] = filemtime($fullpath);
  561. $arrayofSessions[$idsess]["raw"] = $sessValues;
  562. }
  563. }
  564. }
  565. }
  566. @closedir($dh);
  567. }
  568. return $arrayofSessions;
  569. }
  570. /**
  571. * Purge existing sessions
  572. *
  573. * @param int $mysessionid To avoid to try to delete my own session
  574. * @return int >0 if OK, <0 if KO
  575. */
  576. function purgeSessions($mysessionid)
  577. {
  578. global $conf;
  579. $arrayofSessions = array();
  580. $sessPath = ini_get("session.save_path")."/";
  581. dol_syslog('admin.lib:purgeSessions mysessionid='.$mysessionid.' sessPath='.$sessPath);
  582. $error=0;
  583. $dh = @opendir(dol_osencode($sessPath));
  584. while(($file = @readdir($dh)) !== false)
  585. {
  586. if ($file != "." && $file != "..")
  587. {
  588. $fullpath = $sessPath.$file;
  589. if(! @is_dir($fullpath))
  590. {
  591. $sessValues = file_get_contents($fullpath); // get raw session data
  592. if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
  593. preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i',$sessValues) && // limit to current entity
  594. preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
  595. {
  596. $tmp=explode('_', $file);
  597. $idsess=$tmp[1];
  598. // We remove session if it's not ourself
  599. if ($idsess != $mysessionid)
  600. {
  601. $res=@unlink($fullpath);
  602. if (! $res) $error++;
  603. }
  604. }
  605. }
  606. }
  607. }
  608. @closedir($dh);
  609. if (! $error) return 1;
  610. else return -$error;
  611. }
  612. /**
  613. * Enable a module
  614. *
  615. * @param string $value Name of module to activate
  616. * @param int $withdeps Activate/Disable also all dependencies
  617. * @return array array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added);
  618. */
  619. function activateModule($value,$withdeps=1)
  620. {
  621. global $db, $modules, $langs, $conf;
  622. // Check parameters
  623. if (empty($value)) {
  624. $ret['errors'][] = 'ErrorBadParameter';
  625. return $ret;
  626. }
  627. $ret=array('nbmodules'=>0, 'errors'=>array(), 'nbperms'=>0);
  628. $modName = $value;
  629. $modFile = $modName . ".class.php";
  630. // Loop on each directory to fill $modulesdir
  631. $modulesdir = dolGetModulesDirs();
  632. // Loop on each modulesdir directories
  633. $found=false;
  634. foreach ($modulesdir as $dir)
  635. {
  636. if (file_exists($dir.$modFile))
  637. {
  638. $found=@include_once $dir.$modFile;
  639. if ($found) break;
  640. }
  641. }
  642. $objMod = new $modName($db);
  643. // Test if PHP version ok
  644. $verphp=versionphparray();
  645. $vermin=isset($objMod->phpmin)?$objMod->phpmin:0;
  646. if (is_array($vermin) && versioncompare($verphp, $vermin) < 0) {
  647. $ret['errors'][] = $langs->trans("ErrorModuleRequirePHPVersion", versiontostring($vermin));
  648. return $ret;
  649. }
  650. // Test if Dolibarr version ok
  651. $verdol=versiondolibarrarray();
  652. $vermin=isset($objMod->need_dolibarr_version)?$objMod->need_dolibarr_version:0;
  653. //print 'eee '.versioncompare($verdol,$vermin).' - '.join(',',$verdol).' - '.join(',',$vermin);exit;
  654. if (is_array($vermin) && versioncompare($verdol, $vermin) < 0) {
  655. $ret['errors'][] = $langs->trans("ErrorModuleRequireDolibarrVersion", versiontostring($vermin));
  656. return $ret;
  657. }
  658. // Test if javascript requirement ok
  659. if (!empty($objMod->need_javascript_ajax) && empty($conf->use_javascript_ajax)) {
  660. $ret['errors'][] = $langs->trans("ErrorModuleRequireJavascript");
  661. return $ret;
  662. }
  663. $const_name = $objMod->const_name;
  664. if(!empty($conf->global->$const_name)){
  665. return $ret;
  666. }
  667. $result=$objMod->init();
  668. if ($result <= 0)
  669. {
  670. $ret['errors'][]=$objMod->error;
  671. }
  672. else
  673. {
  674. if ($withdeps)
  675. {
  676. if (isset($objMod->depends) && is_array($objMod->depends) && ! empty($objMod->depends))
  677. {
  678. // Activation des modules dont le module depend
  679. $num = count($objMod->depends);
  680. for ($i = 0; $i < $num; $i++)
  681. {
  682. $activate = false;
  683. foreach ($modulesdir as $dir)
  684. {
  685. if (file_exists($dir.$objMod->depends[$i].".class.php"))
  686. {
  687. $resarray = activateModule($objMod->depends[$i]);
  688. if (empty($resarray['errors'])){
  689. $activate = true;
  690. }else{
  691. foreach ($resarray['errors'] as $errorMessage){
  692. dol_syslog($errorMessage, LOG_ERR);
  693. }
  694. }
  695. break;
  696. }
  697. }
  698. if ($activate)
  699. {
  700. $ret['nbmodules']+=$resarray['nbmodules'];
  701. $ret['nbperms']+=$resarray['nbperms'];
  702. }
  703. else
  704. {
  705. $ret['errors'][] = $langs->trans('activateModuleDependNotSatisfied', $objMod->name, $objMod->depends[$i]);
  706. }
  707. }
  708. }
  709. if (isset($objMod->conflictwith) && is_array($objMod->conflictwith) && ! empty($objMod->conflictwith))
  710. {
  711. // Desactivation des modules qui entrent en conflit
  712. $num = count($objMod->conflictwith);
  713. for ($i = 0; $i < $num; $i++)
  714. {
  715. foreach ($modulesdir as $dir)
  716. {
  717. if (file_exists($dir.$objMod->conflictwith[$i].".class.php"))
  718. {
  719. unActivateModule($objMod->conflictwith[$i],0);
  720. }
  721. }
  722. }
  723. }
  724. }
  725. }
  726. if (! count($ret['errors']))
  727. {
  728. $ret['nbmodules']++;
  729. $ret['nbperms']+=count($objMod->rights);
  730. }
  731. return $ret;
  732. }
  733. /**
  734. * Disable a module
  735. *
  736. * @param string $value Nom du module a desactiver
  737. * @param int $requiredby 1=Desactive aussi modules dependants
  738. * @return string Error message or '';
  739. */
  740. function unActivateModule($value, $requiredby=1)
  741. {
  742. global $db, $modules, $conf;
  743. // Check parameters
  744. if (empty($value)) return 'ErrorBadParameter';
  745. $ret='';
  746. $modName = $value;
  747. $modFile = $modName . ".class.php";
  748. // Loop on each directory to fill $modulesdir
  749. $modulesdir = dolGetModulesDirs();
  750. // Loop on each modulesdir directories
  751. $found=false;
  752. foreach ($modulesdir as $dir)
  753. {
  754. if (file_exists($dir.$modFile))
  755. {
  756. $found=@include_once $dir.$modFile;
  757. if ($found) break;
  758. }
  759. }
  760. if ($found)
  761. {
  762. $objMod = new $modName($db);
  763. $result=$objMod->remove();
  764. if ($result <= 0) $ret=$objMod->error;
  765. }
  766. else
  767. {
  768. //print $dir.$modFile;
  769. // 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
  770. $genericMod = new DolibarrModules($db);
  771. $genericMod->name=preg_replace('/^mod/i','',$modName);
  772. $genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName));
  773. $genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName));
  774. dol_syslog("modules::unActivateModule Failed to find module file, we use generic function with name " . $modName);
  775. $genericMod->_remove(array());
  776. }
  777. // Desactivation des modules qui dependent de lui
  778. if (! $ret && $requiredby)
  779. {
  780. $countrb=count($objMod->requiredby);
  781. for ($i = 0; $i < $countrb; $i++)
  782. {
  783. //var_dump($objMod->requiredby[$i]);
  784. unActivateModule($objMod->requiredby[$i]);
  785. }
  786. }
  787. return $ret;
  788. }
  789. /**
  790. * Add external modules to list of dictionaries
  791. *
  792. * @param array $taborder Taborder
  793. * @param array $tabname Tabname
  794. * @param array $tablib Tablib
  795. * @param array $tabsql Tabsql
  796. * @param array $tabsqlsort Tabsqlsort
  797. * @param array $tabfield Tabfield
  798. * @param array $tabfieldvalue Tabfieldvalue
  799. * @param array $tabfieldinsert Tabfieldinsert
  800. * @param array $tabrowid Tabrowid
  801. * @param array $tabcond Tabcond
  802. * @param array $tabhelp Tabhelp
  803. * @param array $tabfieldcheck Tabfieldcheck
  804. * @return int 1
  805. */
  806. function complete_dictionary_with_modules(&$taborder,&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond,&$tabhelp,&$tabfieldcheck)
  807. {
  808. global $db, $modules, $conf, $langs;
  809. // Search modules
  810. $modulesdir = dolGetModulesDirs();
  811. $i = 0; // is a sequencer of modules found
  812. $j = 0; // j is module number. Automatically affected if module number not defined.
  813. foreach ($modulesdir as $dir)
  814. {
  815. // Load modules attributes in arrays (name, numero, orders) from dir directory
  816. //print $dir."\n<br>";
  817. dol_syslog("Scan directory ".$dir." for modules");
  818. $handle=@opendir(dol_osencode($dir));
  819. if (is_resource($handle))
  820. {
  821. while (($file = readdir($handle))!==false)
  822. {
  823. //print "$i ".$file."\n<br>";
  824. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  825. {
  826. $modName = substr($file, 0, dol_strlen($file) - 10);
  827. if ($modName)
  828. {
  829. include_once $dir.$file;
  830. $objMod = new $modName($db);
  831. if ($objMod->numero > 0)
  832. {
  833. $j = $objMod->numero;
  834. }
  835. else
  836. {
  837. $j = 1000 + $i;
  838. }
  839. $modulequalified=1;
  840. // We discard modules according to features level (PS: if module is activated we always show it)
  841. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  842. if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
  843. if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
  844. //If module is not activated disqualified
  845. if (empty($conf->global->$const_name)) $modulequalified=0;
  846. if ($modulequalified)
  847. {
  848. // Load languages files of module
  849. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  850. {
  851. foreach($objMod->langfiles as $langfile)
  852. {
  853. $langs->load($langfile);
  854. }
  855. }
  856. // Complete arrays
  857. //&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond
  858. if (empty($objMod->dictionaries) && ! empty($objMod->dictionnaries)) $objMod->dictionaries=$objMod->dictionnaries; // For backward compatibility
  859. if (! empty($objMod->dictionaries))
  860. {
  861. //var_dump($objMod->dictionaries['tabname']);
  862. $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp=0;
  863. foreach($objMod->dictionaries['tabname'] as $val) { $nbtabname++; $taborder[] = max($taborder)+1; $tabname[] = $val; }
  864. foreach($objMod->dictionaries['tablib'] as $val) { $nbtablib++; $tablib[] = $val; }
  865. foreach($objMod->dictionaries['tabsql'] as $val) { $nbtabsql++; $tabsql[] = $val; }
  866. foreach($objMod->dictionaries['tabsqlsort'] as $val) { $nbtabsqlsort++; $tabsqlsort[] = $val; }
  867. foreach($objMod->dictionaries['tabfield'] as $val) { $nbtabfield++; $tabfield[] = $val; }
  868. foreach($objMod->dictionaries['tabfieldvalue'] as $val) { $nbtabfieldvalue++; $tabfieldvalue[] = $val; }
  869. foreach($objMod->dictionaries['tabfieldinsert'] as $val) { $nbtabfieldinsert++; $tabfieldinsert[] = $val; }
  870. foreach($objMod->dictionaries['tabrowid'] as $val) { $nbtabrowid++; $tabrowid[] = $val; }
  871. foreach($objMod->dictionaries['tabcond'] as $val) { $nbtabcond++; $tabcond[] = $val; }
  872. if (! empty($objMod->dictionaries['tabhelp'])) foreach($objMod->dictionaries['tabhelp'] as $val) { $nbtabhelp++; $tabhelp[] = $val; }
  873. if (! empty($objMod->dictionaries['tabfieldcheck'])) foreach($objMod->dictionaries['tabfieldcheck'] as $val) { $nbtabfieldcheck++; $tabfieldcheck[] = $val; }
  874. if ($nbtabname != $nbtablib || $nbtablib != $nbtabsql || $nbtabsql != $nbtabsqlsort)
  875. {
  876. print 'Error in descriptor of module '.$const_name.'. Array ->dictionaries has not same number of record for key "tabname", "tablib", "tabsql" and "tabsqlsort"';
  877. //print "$const_name: $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp\n";
  878. }
  879. }
  880. $j++;
  881. $i++;
  882. }
  883. else dol_syslog("Module ".get_class($objMod)." not qualified");
  884. }
  885. }
  886. }
  887. closedir($handle);
  888. }
  889. else
  890. {
  891. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  892. }
  893. }
  894. return 1;
  895. }
  896. /**
  897. * Add external modules to list of contact element
  898. *
  899. * @param array $elementList elementList
  900. * @return int 1
  901. */
  902. function complete_elementList_with_modules(&$elementList)
  903. {
  904. global $db, $modules, $conf, $langs;
  905. // Search modules
  906. $filename = array();
  907. $modules = array();
  908. $orders = array();
  909. $categ = array();
  910. $dirmod = array();
  911. $i = 0; // is a sequencer of modules found
  912. $j = 0; // j is module number. Automatically affected if module number not defined.
  913. $modulesdir = dolGetModulesDirs();
  914. foreach ($modulesdir as $dir)
  915. {
  916. // Load modules attributes in arrays (name, numero, orders) from dir directory
  917. //print $dir."\n<br>";
  918. dol_syslog("Scan directory ".$dir." for modules");
  919. $handle=@opendir(dol_osencode($dir));
  920. if (is_resource($handle))
  921. {
  922. while (($file = readdir($handle))!==false)
  923. {
  924. //print "$i ".$file."\n<br>";
  925. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  926. {
  927. $modName = substr($file, 0, dol_strlen($file) - 10);
  928. if ($modName)
  929. {
  930. include_once $dir.$file;
  931. $objMod = new $modName($db);
  932. if ($objMod->numero > 0)
  933. {
  934. $j = $objMod->numero;
  935. }
  936. else
  937. {
  938. $j = 1000 + $i;
  939. }
  940. $modulequalified=1;
  941. // We discard modules according to features level (PS: if module is activated we always show it)
  942. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  943. if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
  944. if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
  945. //If module is not activated disqualified
  946. if (empty($conf->global->$const_name)) $modulequalified=0;
  947. if ($modulequalified)
  948. {
  949. // Load languages files of module
  950. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  951. {
  952. foreach($objMod->langfiles as $langfile)
  953. {
  954. $langs->load($langfile);
  955. }
  956. }
  957. $modules[$i] = $objMod;
  958. $filename[$i]= $modName;
  959. $orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module
  960. //print "x".$modName." ".$orders[$i]."\n<br>";
  961. if (isset($categ[$objMod->special])) $categ[$objMod->special]++; // Array of all different modules categories
  962. else $categ[$objMod->special]=1;
  963. $dirmod[$i] = $dirroot;
  964. if (! empty($objMod->module_parts['contactelement']))
  965. {
  966. $elementList[$objMod->name] = $langs->trans($objMod->name);
  967. }
  968. $j++;
  969. $i++;
  970. }
  971. else dol_syslog("Module ".get_class($objMod)." not qualified");
  972. }
  973. }
  974. }
  975. closedir($handle);
  976. }
  977. else
  978. {
  979. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  980. }
  981. }
  982. return 1;
  983. }
  984. /**
  985. * Show array with constants to edit
  986. *
  987. * @param array $tableau Array of constants
  988. * @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
  989. * @return void
  990. */
  991. function form_constantes($tableau,$strictw3c=0)
  992. {
  993. global $db,$bc,$langs,$conf,$_Avery_Labels;
  994. $form = new Form($db);
  995. if (! empty($strictw3c) && $strictw3c == 1) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  996. print '<table class="noborder" width="100%">';
  997. print '<tr class="liste_titre">';
  998. print '<td>'.$langs->trans("Description").'</td>';
  999. print '<td>'.$langs->trans("Value").'*</td>';
  1000. if (empty($strictw3c)) print '<td align="center" width="80">'.$langs->trans("Action").'</td>';
  1001. print "</tr>\n";
  1002. $var=true;
  1003. $listofparam=array();
  1004. foreach($tableau as $const) // Loop on each param
  1005. {
  1006. $sql = "SELECT ";
  1007. $sql.= "rowid";
  1008. $sql.= ", ".$db->decrypt('name')." as name";
  1009. $sql.= ", ".$db->decrypt('value')." as value";
  1010. $sql.= ", type";
  1011. $sql.= ", note";
  1012. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  1013. $sql.= " WHERE ".$db->decrypt('name')." = '".$const."'";
  1014. $sql.= " AND entity IN (0, ".$conf->entity.")";
  1015. $sql.= " ORDER BY name ASC, entity DESC";
  1016. $result = $db->query($sql);
  1017. dol_syslog("List params", LOG_DEBUG);
  1018. if ($result)
  1019. {
  1020. $obj = $db->fetch_object($result); // Take first result of select
  1021. $var=!$var;
  1022. // For avoid warning in strict mode
  1023. if (empty($obj)) {
  1024. $obj = (object) array('rowid'=>'','name'=>'','value'=>'','type'=>'','note'=>'');
  1025. }
  1026. if (empty($strictw3c)) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  1027. print "<tr ".$bc[$var].">";
  1028. // Show constant
  1029. print '<td>';
  1030. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  1031. print '<input type="hidden" name="action" value="update">';
  1032. print '<input type="hidden" name="rowid'.(empty($strictw3c)?'':'[]').'" value="'.$obj->rowid.'">';
  1033. print '<input type="hidden" name="constname'.(empty($strictw3c)?'':'[]').'" value="'.$const.'">';
  1034. print '<input type="hidden" name="constnote'.(empty($strictw3c)?'':'[]').'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">';
  1035. print $langs->trans('Desc'.$const);
  1036. if ($const == 'ADHERENT_MAILMAN_URL')
  1037. {
  1038. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick1">'.img_down().'</a><br>';
  1039. //print 'http://lists.exampe.com/cgi-bin/mailman/admin/%LISTE%/members?adminpw=%MAILMAN_ADMINPW%&subscribees=%EMAIL%&send_welcome_msg_to_this_batch=1';
  1040. print '<div id="example1" class="hidden">';
  1041. 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';
  1042. print '</div>';
  1043. }
  1044. if ($const == 'ADHERENT_MAILMAN_UNSUB_URL')
  1045. {
  1046. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick2">'.img_down().'</a><br>';
  1047. print '<div id="example2" class="hidden">';
  1048. 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';
  1049. print '</div>';
  1050. //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
  1051. }
  1052. if ($const == 'ADHERENT_MAILMAN_LISTS')
  1053. {
  1054. print '. '.$langs->trans("Example").': <a href="#" id="exampleclick3">'.img_down().'</a><br>';
  1055. print '<div id="example3" class="hidden">';
  1056. print 'mymailmanlist<br>';
  1057. print 'mymailmanlist1,mymailmanlist2<br>';
  1058. print 'TYPE:Type1:mymailmanlist1,TYPE:Type2:mymailmanlist2<br>';
  1059. if ($conf->categorie->enabled) print 'CATEG:Categ1:mymailmanlist1,CATEG:Categ2:mymailmanlist2<br>';
  1060. print '</div>';
  1061. //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
  1062. }
  1063. print "</td>\n";
  1064. // Value
  1065. if ($const == 'ADHERENT_CARD_TYPE' || $const == 'ADHERENT_ETIQUETTE_TYPE')
  1066. {
  1067. print '<td>';
  1068. // List of possible labels (defined into $_Avery_Labels variable set into format_cards.lib.php)
  1069. require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
  1070. $arrayoflabels=array();
  1071. foreach(array_keys($_Avery_Labels) as $codecards)
  1072. {
  1073. $arrayoflabels[$codecards]=$_Avery_Labels[$codecards]['name'];
  1074. }
  1075. print $form->selectarray('constvalue'.(empty($strictw3c)?'':'[]'),$arrayoflabels,($obj->value?$obj->value:'CARD'),1,0,0);
  1076. print '<input type="hidden" name="consttype" value="yesno">';
  1077. print '</td>';
  1078. }
  1079. else
  1080. {
  1081. print '<td>';
  1082. if (in_array($const,array('ADHERENT_CARD_TEXT','ADHERENT_CARD_TEXT_RIGHT','ADHERENT_ETIQUETTE_TEXT')))
  1083. {
  1084. print '<textarea class="flat" name="constvalue'.(empty($strictw3c)?'':'[]').'" cols="50" rows="5" wrap="soft">'."\n";
  1085. print $obj->value;
  1086. print "</textarea>\n";
  1087. print '<input type="hidden" name="consttype" value="texte">';
  1088. }
  1089. else if (in_array($const,array('ADHERENT_AUTOREGISTER_NOTIF_MAIL','ADHERENT_AUTOREGISTER_MAIL','ADHERENT_MAIL_VALID','ADHERENT_MAIL_COTIS','ADHERENT_MAIL_RESIL')))
  1090. {
  1091. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  1092. $doleditor=new DolEditor('constvalue_'.$const.(empty($strictw3c)?'':'[]'),$obj->value,'',160,'dolibarr_notes','',false,false,$conf->fckeditor->enabled,ROWS_5,'90%');
  1093. $doleditor->Create();
  1094. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="texte">';
  1095. }
  1096. else if ($obj->type == 'yesno')
  1097. {
  1098. print $form->selectyesno('constvalue'.(empty($strictw3c)?'':'[]'),$obj->value,1);
  1099. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="yesno">';
  1100. }
  1101. else
  1102. {
  1103. print '<input type="text" class="flat" size="48" name="constvalue'.(empty($strictw3c)?'':'[]').'" value="'.dol_escape_htmltag($obj->value).'">';
  1104. print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="chaine">';
  1105. }
  1106. print '</td>';
  1107. }
  1108. // Submit
  1109. if (empty($strictw3c))
  1110. {
  1111. print '<td align="center">';
  1112. print '<input type="submit" class="button" value="'.$langs->trans("Update").'" name="Button">';
  1113. print "</td>";
  1114. }
  1115. print "</tr>\n";
  1116. if (empty($strictw3c)) print "</form>\n";
  1117. }
  1118. }
  1119. print '</table>';
  1120. if (! empty($strictw3c) && $strictw3c == 1)
  1121. {
  1122. print '<div align="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
  1123. print "</form>\n";
  1124. }
  1125. }
  1126. /**
  1127. * Show array with constants to edit
  1128. *
  1129. * @param array $modules Array of all modules
  1130. * @return string HTML string with warning
  1131. */
  1132. function showModulesExludedForExternal($modules)
  1133. {
  1134. global $conf,$langs;
  1135. $text=$langs->trans("OnlyFollowingModulesAreOpenedToExternalUsers");
  1136. $listofmodules=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL);
  1137. $i=0;
  1138. if (!empty($modules)) {
  1139. foreach($modules as $module)
  1140. {
  1141. $moduleconst=$module->const_name;
  1142. $modulename=strtolower($module->name);
  1143. //print 'modulename='.$modulename;
  1144. //if (empty($conf->global->$moduleconst)) continue;
  1145. if (! in_array($modulename,$listofmodules)) continue;
  1146. //var_dump($modulename.'eee'.$langs->trans('Module'.$module->numero.'Name'));
  1147. if ($i > 0) $text.=', ';
  1148. else $text.=' ';
  1149. $i++;
  1150. $text .= $langs->trans('Module'.$module->numero.'Name');
  1151. }
  1152. }
  1153. return $text;
  1154. }
  1155. /**
  1156. * Add document model used by doc generator
  1157. *
  1158. * @param string $name Model name
  1159. * @param string $type Model type
  1160. * @param string $label Model label
  1161. * @param string $description Model description
  1162. * @return int <0 if KO, >0 if OK
  1163. */
  1164. function addDocumentModel($name, $type, $label='', $description='')
  1165. {
  1166. global $db, $conf;
  1167. $db->begin();
  1168. $sql = "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity, libelle, description)";
  1169. $sql.= " VALUES ('".$db->escape($name)."','".$type."',".$conf->entity.", ";
  1170. $sql.= ($label?"'".$db->escape($label)."'":'null').", ";
  1171. $sql.= (! empty($description)?"'".$db->escape($description)."'":"null");
  1172. $sql.= ")";
  1173. dol_syslog("admin.lib::addDocumentModel", LOG_DEBUG);
  1174. $resql=$db->query($sql);
  1175. if ($resql)
  1176. {
  1177. $db->commit();
  1178. return 1;
  1179. }
  1180. else
  1181. {
  1182. dol_print_error($db);
  1183. $db->rollback();
  1184. return -1;
  1185. }
  1186. }
  1187. /**
  1188. * Delete document model used by doc generator
  1189. *
  1190. * @param string $name Model name
  1191. * @param string $type Model type
  1192. * @return int <0 if KO, >0 if OK
  1193. */
  1194. function delDocumentModel($name, $type)
  1195. {
  1196. global $db, $conf;
  1197. $db->begin();
  1198. $sql = "DELETE FROM ".MAIN_DB_PREFIX."document_model";
  1199. $sql.= " WHERE nom = '".$db->escape($name)."'";
  1200. $sql.= " AND type = '".$type."'";
  1201. $sql.= " AND entity = ".$conf->entity;
  1202. dol_syslog("admin.lib::delDocumentModel", LOG_DEBUG);
  1203. $resql=$db->query($sql);
  1204. if ($resql)
  1205. {
  1206. $db->commit();
  1207. return 1;
  1208. }
  1209. else
  1210. {
  1211. dol_print_error($db);
  1212. $db->rollback();
  1213. return -1;
  1214. }
  1215. }
  1216. /**
  1217. * Return the php_info into an array
  1218. *
  1219. * @return array Array with PHP infos
  1220. */
  1221. function phpinfo_array()
  1222. {
  1223. ob_start();
  1224. phpinfo();
  1225. $info_arr = array();
  1226. $info_lines = explode("\n", strip_tags(ob_get_clean(), "<tr><td><h2>")); // end of ob_start()
  1227. $cat = "General";
  1228. foreach($info_lines as $line)
  1229. {
  1230. // new cat?
  1231. preg_match("~<h2>(.*)</h2>~", $line, $title) ? $cat = $title[1] : null;
  1232. if(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
  1233. {
  1234. $info_arr[trim($cat)][trim($val[1])] = $val[2];
  1235. }
  1236. elseif(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
  1237. {
  1238. $info_arr[trim($cat)][trim($val[1])] = array("local" => $val[2], "master" => $val[3]);
  1239. }
  1240. }
  1241. return $info_arr;
  1242. }