Completed
Branch develop (7272ee)
by
unknown
41:48
created

admin.lib.php ➔ company_admin_prepare_head()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 0
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2008-2011  Laurent Destailleur     <[email protected]>
3
 * Copyright (C) 2005-2016  Regis Houssin           <[email protected]>
4
 * Copyright (C) 2012       J. Fernando Lagrange    <[email protected]>
5
 * Copyright (C) 2015       Raphaël Doursenaud      <[email protected]>
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
/**
23
 *	\file			htdocs/core/lib/admin.lib.php
24
 *  \brief			Library of admin functions
25
 */
26
27
require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
28
29
/**
30
 *  Renvoi une version en chaine depuis une version en tableau
31
 *
32
 *  @param		array		$versionarray		Tableau de version (vermajeur,vermineur,autre)
33
 *  @return     string        			      	Chaine version
34
 */
35
function versiontostring($versionarray)
36
{
37
    $string='?';
38
    if (isset($versionarray[0])) $string=$versionarray[0];
39
    if (isset($versionarray[1])) $string.='.'.$versionarray[1];
40
    if (isset($versionarray[2])) $string.='.'.$versionarray[2];
41
    return $string;
42
}
43
44
/**
45
 *	Compare 2 versions (stored into 2 arrays).
46
 *  To check if Dolibarr version is lower than (x,y,z), do "if versioncompare(versiondolibarrarray(), array(x.y.z)) <= 0"
47
 *  For example: if (versioncompare(versiondolibarrarray(),array(4,0,-4)) >= 0) is true if version is 4.0 alpha or higher.
48
 *  For example: if (versioncompare(versiondolibarrarray(),array(4,0,0)) >= 0) is true if version is 4.0 final or higher.
49
 *  For example: if (versioncompare(versiondolibarrarray(),array(4,0,1)) >= 0) is true if version is 4.0.1 or higher.
50
 *  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)
51
 *
52
 *	@param      array		$versionarray1      Array of version (vermajor,verminor,patch)
53
 *	@param      array		$versionarray2		Array of version (vermajor,verminor,patch)
54
 *	@return     int          			       	-4,-3,-2,-1 if versionarray1<versionarray2 (value depends on level of difference)
55
 * 												0 if same
56
 * 												1,2,3,4 if versionarray1>versionarray2 (value depends on level of difference)
57
 */
58
function versioncompare($versionarray1,$versionarray2)
59
{
60
    $ret=0;
61
    $level=0;
62
    $count1=count($versionarray1);
63
    $count2=count($versionarray2);
64
    $maxcount=max($count1,$count2);
65
    while ($level < $maxcount)
66
    {
67
        $operande1=isset($versionarray1[$level])?$versionarray1[$level]:0;
68
        $operande2=isset($versionarray2[$level])?$versionarray2[$level]:0;
69
        if (preg_match('/alpha|dev/i',$operande1)) $operande1=-5;
70
        if (preg_match('/alpha|dev/i',$operande2)) $operande2=-5;
71
        if (preg_match('/beta$/i',$operande1)) $operande1=-4;
72
        if (preg_match('/beta$/i',$operande2)) $operande2=-4;
73
        if (preg_match('/beta([0-9])+/i',$operande1)) $operande1=-3;
74
        if (preg_match('/beta([0-9])+/i',$operande2)) $operande2=-3;
75
        if (preg_match('/rc$/i',$operande1)) $operande1=-2;
76
        if (preg_match('/rc$/i',$operande2)) $operande2=-2;
77
        if (preg_match('/rc([0-9])+/i',$operande1)) $operande1=-1;
78
        if (preg_match('/rc([0-9])+/i',$operande2)) $operande2=-1;
79
        $level++;
80
        //print 'level '.$level.' '.$operande1.'-'.$operande2.'<br>';
81
        if ($operande1 < $operande2) { $ret = -$level; break; }
82
        if ($operande1 > $operande2) { $ret = $level; break; }
83
    }
84
    //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n";
85
    return $ret;
86
}
87
88
89
/**
90
 *	Return version PHP
91
 *
92
 *	@return     array               Tableau de version (vermajeur,vermineur,autre)
93
 */
94
function versionphparray()
95
{
96
    return explode('.',PHP_VERSION);
97
}
98
99
/**
100
 *	Return version Dolibarr
101
 *
102
 *	@return     array               Tableau de version (vermajeur,vermineur,autre)
103
 */
104
function versiondolibarrarray()
105
{
106
    return explode('.',DOL_VERSION);
107
}
108
109
110
/**
111
 *	Launch a sql file. Function used by:
112
 *  - Migrate process (dolibarr-xyz-abc.sql)
113
 *  - Loading sql menus (auguria)
114
 *  - Running specific Sql by a module init
115
 *  Install process however does not use it.
116
 *  Note that Sql files must have all comments at start of line.
117
 *
118
 *	@param		string	$sqlfile		Full path to sql file
119
 * 	@param		int		$silent			1=Do not output anything, 0=Output line for update page
120
 * 	@param		int		$entity			Entity targeted for multicompany module
121
 *	@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).
122
 *	@param		string	$handler		Handler targeted for menu
123
 *	@param 		string	$okerror		Family of errors we accept ('default', 'none')
124
 * 	@return		int						<=0 if KO, >0 if OK
125
 */
126
function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$okerror='default')
127
{
128
    global $db, $conf, $langs, $user;
129
130
    dol_syslog("Admin.lib::run_sql run sql file ".$sqlfile." silent=".$silent." entity=".$entity." usesavepoint=".$usesavepoint." handler=".$handler." okerror=".$okerror, LOG_DEBUG);
131
132
    $ok=0;
133
    $error=0;
134
    $i=0;
135
    $buffer = '';
136
    $arraysql = array();
137
138
    // Get version of database
139
    $versionarray=$db->getVersionArray();
140
141
    $fp = fopen($sqlfile,"r");
142
    if ($fp)
143
    {
144
        while (! feof($fp))
145
        {
146
            $buf = fgets($fp, 32768);
147
148
            // Test if request must be ran only for particular database or version (if yes, we must remove the -- comment)
149
            if (preg_match('/^--\sV(MYSQL|PGSQL)([^\s]*)/i',$buf,$reg))
150
            {
151
            	$qualified=1;
152
153
            	// restrict on database type
154
            	if (! empty($reg[1]))
155
            	{
156
            		if (! preg_match('/'.preg_quote($reg[1]).'/i',$db->type)) $qualified=0;
157
            	}
158
159
            	// restrict on version
160
            	if ($qualified)
161
            	{
162
            		if (! empty($reg[2]))
163
            		{
164
            			if (is_numeric($reg[2]))	// This is a version
165
            			{
166
			                $versionrequest=explode('.',$reg[2]);
167
			                //print var_dump($versionrequest);
168
			                //print var_dump($versionarray);
169
			                if (! count($versionrequest) || ! count($versionarray) || versioncompare($versionrequest,$versionarray) > 0)
170
			                {
171
			                	$qualified=0;
172
			                }
173
            			}
174
            			else						// This is a test on a constant. For example when we have -- VMYSQLUTF8UNICODE, we test constant $conf->global->UTF8UNICODE
175
            			{
176
            				$dbcollation = strtoupper(preg_replace('/_/', '', $conf->db->dolibarr_main_db_collation));
177
            				//var_dump($reg[2]);
178
            				//var_dump($dbcollation);
179
            				if (empty($conf->db->dolibarr_main_db_collation) || ($reg[2] != $dbcollation)) $qualified=0;
180
            				//var_dump($qualified);
181
            			}
182
            		}
183
            	}
184
185
                if ($qualified)
186
                {
187
                    // Version qualified, delete SQL comments
188
                    $buf=preg_replace('/^--\sV(MYSQL|PGSQL)([^\s]*)/i','',$buf);
189
                    //print "Ligne $i qualifi?e par version: ".$buf.'<br>';
190
                }
191
            }
192
193
            // Add line buf to buffer if not a comment
194
            if (! preg_match('/^\s*--/',$buf))
195
            {
196
                $buf=preg_replace('/([,;ERLT\)])\s*--.*$/i','\1',$buf); //remove comment from a line that not start with -- before add it to the buffer
197
                $buffer .= trim($buf);
198
            }
199
200
            //          print $buf.'<br>';
201
202
            if (preg_match('/;/',$buffer))	// If string contains ';', it's end of a request string, we save it in arraysql.
203
            {
204
                // Found new request
205
                if ($buffer) $arraysql[$i]=$buffer;
206
                $i++;
207
                $buffer='';
208
            }
209
        }
210
211
        if ($buffer) $arraysql[$i]=$buffer;
212
        fclose($fp);
213
    }
214
    else
215
    {
216
        dol_syslog("Admin.lib::run_sql failed to open file ".$sqlfile, LOG_ERR);
217
    }
218
219
    // Loop on each request to see if there is a __+MAX_table__ key
220
    $listofmaxrowid=array();	// This is a cache table
221
    foreach($arraysql as $i => $sql)
222
    {
223
        $newsql=$sql;
224
225
        // Replace __+MAX_table__ with max of table
226
        while (preg_match('/__\+MAX_([A-Za-z_]+)__/i',$newsql,$reg))
227
        {
228
            $table=$reg[1];
229
            if (! isset($listofmaxrowid[$table]))
230
            {
231
                //var_dump($db);
232
                $sqlgetrowid='SELECT MAX(rowid) as max from '.$table;
233
                $resql=$db->query($sqlgetrowid);
234
                if ($resql)
235
                {
236
                    $obj=$db->fetch_object($resql);
237
                    $listofmaxrowid[$table]=$obj->max;
238
                    if (empty($listofmaxrowid[$table])) $listofmaxrowid[$table]=0;
239
                }
240
                else
241
                {
242
                    if (! $silent) print '<tr><td valign="top" colspan="2">';
243
                    if (! $silent) print '<div class="error">'.$langs->trans("Failed to get max rowid for ".$table)."</div></td>";
244
                    if (! $silent) print '</tr>';
245
                    $error++;
246
                    break;
247
                }
248
            }
249
            $from='__+MAX_'.$table.'__';
250
            $to='+'.$listofmaxrowid[$table];
251
            $newsql=str_replace($from,$to,$newsql);
252
            dol_syslog('Admin.lib::run_sql New Request '.($i+1).' (replacing '.$from.' to '.$to.')', LOG_DEBUG);
253
254
            $arraysql[$i]=$newsql;
255
        }
256
    }
257
258
    // Loop on each request to execute request
259
    $cursorinsert=0;
260
    $listofinsertedrowid=array();
261
    foreach($arraysql as $i => $sql)
262
    {
263
        if ($sql)
264
        {
265
        	// Replace the prefix tables
266
        	if (MAIN_DB_PREFIX != 'llx_')
267
        	{
268
        		$sql=preg_replace('/llx_/i',MAIN_DB_PREFIX,$sql);
269
        	}
270
271
            if (!empty($handler)) $sql=preg_replace('/__HANDLER__/i',"'".$handler."'",$sql);
272
273
            $newsql=preg_replace('/__ENTITY__/i',(!empty($entity)?$entity:$conf->entity),$sql);
274
275
            // Ajout trace sur requete (eventuellement a commenter si beaucoup de requetes)
276
            if (! $silent) print '<tr><td class="tdtop">'.$langs->trans("Request").' '.($i+1)." sql='".dol_htmlentities($newsql,ENT_NOQUOTES)."'</td></tr>\n";
277
            dol_syslog('Admin.lib::run_sql Request '.($i+1), LOG_DEBUG);
278
			$sqlmodified=0;
279
280
            // Replace for encrypt data
281
            if (preg_match_all('/__ENCRYPT\(\'([^\']+)\'\)__/i',$newsql,$reg))
282
            {
283
                $num=count($reg[0]);
284
285
                for($j=0;$j<$num;$j++)
286
                {
287
                    $from 	= $reg[0][$j];
288
                    $to		= $db->encrypt($reg[1][$j],1);
289
                    $newsql	= str_replace($from,$to,$newsql);
290
                }
291
                $sqlmodified++;
292
            }
293
294
            // Replace for decrypt data
295
            if (preg_match_all('/__DECRYPT\(\'([A-Za-z0-9_]+)\'\)__/i',$newsql,$reg))
296
            {
297
                $num=count($reg[0]);
298
299
                for($j=0;$j<$num;$j++)
300
                {
301
                    $from 	= $reg[0][$j];
302
                    $to		= $db->decrypt($reg[1][$j]);
303
                    $newsql	= str_replace($from,$to,$newsql);
304
                }
305
                $sqlmodified++;
306
            }
307
308
            // Replace __x__ with rowid of insert nb x
309
            while (preg_match('/__([0-9]+)__/',$newsql,$reg))
310
            {
311
                $cursor=$reg[1];
312
                if (empty($listofinsertedrowid[$cursor]))
313
                {
314
                    if (! $silent) print '<tr><td valign="top" colspan="2">';
315
                    if (! $silent) print '<div class="error">'.$langs->trans("FileIsNotCorrect")."</div></td>";
316
                    if (! $silent) print '</tr>';
317
                    $error++;
318
                    break;
319
                }
320
                $from='__'.$cursor.'__';
321
                $to=$listofinsertedrowid[$cursor];
322
                $newsql=str_replace($from,$to,$newsql);
323
                $sqlmodified++;
324
            }
325
326
            if ($sqlmodified) dol_syslog('Admin.lib::run_sql New Request '.($i+1), LOG_DEBUG);
327
328
            $result=$db->query($newsql,$usesavepoint);
329
            if ($result)
330
            {
331
                if (! $silent) print '<!-- Result = OK -->'."\n";
332
333
                if (preg_replace('/insert into ([^\s]+)/i',$newsql,$reg))
334
                {
335
                    $cursorinsert++;
336
337
                    // It's an insert
338
                    $table=preg_replace('/([^a-zA-Z_]+)/i','',$reg[1]);
339
                    $insertedrowid=$db->last_insert_id($table);
340
                    $listofinsertedrowid[$cursorinsert]=$insertedrowid;
341
                    dol_syslog('Admin.lib::run_sql Insert nb '.$cursorinsert.', done in table '.$table.', rowid is '.$listofinsertedrowid[$cursorinsert], LOG_DEBUG);
342
                }
343
                // 	          print '<td align="right">OK</td>';
344
            }
345
            else
346
            {
347
                $errno=$db->errno();
348
                if (! $silent) print '<!-- Result = '.$errno.' -->'."\n";
349
350
				// Define list of errors we accept (array $okerrors)
351
            	$okerrors=array(	// By default
352
					'DB_ERROR_TABLE_ALREADY_EXISTS',
353
					'DB_ERROR_COLUMN_ALREADY_EXISTS',
354
					'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
355
					'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS',		// PgSql use same code for table and key already exist
356
					'DB_ERROR_RECORD_ALREADY_EXISTS',
357
					'DB_ERROR_NOSUCHTABLE',
358
					'DB_ERROR_NOSUCHFIELD',
359
					'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
360
					'DB_ERROR_NO_INDEX_TO_DROP',
361
					'DB_ERROR_CANNOT_CREATE',    		// Qd contrainte deja existante
362
					'DB_ERROR_CANT_DROP_PRIMARY_KEY',
363
					'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
364
            		'DB_ERROR_22P02'
365
				);
366
                if ($okerror == 'none') $okerrors=array();
367
368
                // Is it an error we accept
369
				if (! in_array($errno,$okerrors))
370
				{
371
				    if (! $silent) print '<tr><td valign="top" colspan="2">';
372
				    if (! $silent) print '<div class="error">'.$langs->trans("Error")." ".$db->errno().": ".$newsql."<br>".$db->error()."</div></td>";
373
				    if (! $silent) print '</tr>'."\n";
374
				    dol_syslog('Admin.lib::run_sql Request '.($i+1)." Error ".$db->errno()." ".$newsql."<br>".$db->error(), LOG_ERR);
375
				    $error++;
376
				}
377
            }
378
379
            if (! $silent) print '</tr>'."\n";
380
        }
381
    }
382
383
    if ($error == 0)
384
    {
385
        if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
386
        if (! $silent) print '<td align="right">'.$langs->trans("OK").'</td></tr>'."\n";
387
        $ok = 1;
388
    }
389
    else
390
    {
391
        if (! $silent) print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>';
392
        if (! $silent) print '<td align="right"><font class="error">'.$langs->trans("KO").'</font></td></tr>'."\n";
393
        $ok = 0;
394
    }
395
396
    return $ok;
397
}
398
399
400
/**
401
 *	Effacement d'une constante dans la base de donnees
402
 *
403
 *	@param	    DoliDB		$db         Database handler
404
 *	@param	    string		$name		Name of constant or rowid of line
405
 *	@param	    int			$entity		Multi company id, -1 for all entities
406
 *	@return     int         			<0 if KO, >0 if OK
407
 *
408
 *	@see		dolibarr_get_const, dolibarr_set_const, dol_set_user_param
409
 */
410
function dolibarr_del_const($db, $name, $entity=1)
411
{
412
    global $conf;
413
414
    if (empty($name))
415
    {
416
    	dol_print_error('','Error call dolibar_del_const with parameter name empty');
417
    	return -1;
418
    }
419
420
    $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
421
    $sql.= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'";
422
    if (is_numeric($name)) $sql.= " OR rowid = '".$db->escape($name)."'";
423
    $sql.= ")";
424
    if ($entity >= 0) $sql.= " AND entity = ".$entity;
425
426
    dol_syslog("admin.lib::dolibarr_del_const", LOG_DEBUG);
427
    $resql=$db->query($sql);
428
    if ($resql)
429
    {
430
        $conf->global->$name='';
431
        return 1;
432
    }
433
    else
434
    {
435
        dol_print_error($db);
436
        return -1;
437
    }
438
}
439
440
/**
441
 *	Recupere une constante depuis la base de donnees.
442
 *
443
 *	@param	    DoliDB		$db         Database handler
444
 *	@param	    string		$name		Nom de la constante
445
 *	@param	    int			$entity		Multi company id
446
 *	@return     string      			Valeur de la constante
447
 *
448
 *	@see		dolibarr_del_const, dolibarr_set_const, dol_set_user_param
449
 */
450
function dolibarr_get_const($db, $name, $entity=1)
451
{
452
    global $conf;
453
    $value='';
454
455
    $sql = "SELECT ".$db->decrypt('value')." as value";
456
    $sql.= " FROM ".MAIN_DB_PREFIX."const";
457
    $sql.= " WHERE name = ".$db->encrypt($name,1);
458
    $sql.= " AND entity = ".$entity;
459
460
    dol_syslog("admin.lib::dolibarr_get_const", LOG_DEBUG);
461
    $resql=$db->query($sql);
462
    if ($resql)
463
    {
464
        $obj=$db->fetch_object($resql);
465
        if ($obj) $value=$obj->value;
466
    }
467
    return $value;
468
}
469
470
471
/**
472
 *	Insert a parameter (key,value) into database (delete old key then insert it again).
473
 *
474
 *	@param	    DoliDB		$db         Database handler
475
 *	@param	    string		$name		Name of constant
476
 *	@param	    string		$value		Value of constant
477
 *	@param	    string		$type		Type of constante (chaine par defaut)
478
 *	@param	    int			$visible	Is constant visible in Setup->Other page (0 by default)
479
 *	@param	    string		$note		Note on parameter
480
 *	@param	    int			$entity		Multi company id (0 means all entities)
481
 *	@return     int         			-1 if KO, 1 if OK
482
 *
483
 *	@see		dolibarr_del_const, dolibarr_get_const, dol_set_user_param
484
 */
485
function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
486
{
487
    global $conf;
488
489
    // Clean parameters
490
    $name=trim($name);
491
492
    // Check parameters
493
    if (empty($name))
494
    {
495
        dol_print_error($db,"Error: Call to function dolibarr_set_const with wrong parameters", LOG_ERR);
496
        exit;
497
    }
498
499
    //dol_syslog("dolibarr_set_const name=$name, value=$value type=$type, visible=$visible, note=$note entity=$entity");
500
501
    $db->begin();
502
503
    $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
504
    $sql.= " WHERE name = ".$db->encrypt($name,1);
505
    if ($entity >= 0) $sql.= " AND entity = ".$entity;
506
507
    dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG);
508
    $resql=$db->query($sql);
509
510
    if (strcmp($value,''))	// true if different. Must work for $value='0' or $value=0
511
    {
512
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity)";
513
        $sql.= " VALUES (";
514
        $sql.= $db->encrypt($name,1);
515
        $sql.= ", ".$db->encrypt($value,1);
516
        $sql.= ",'".$db->escape($type)."',".$visible.",'".$db->escape($note)."',".$entity.")";
517
518
        //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit;
519
        //print "xx".$db->escape($value);
520
        dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG);
521
        $resql=$db->query($sql);
522
    }
523
524
    if ($resql)
525
    {
526
        $db->commit();
527
        $conf->global->$name=$value;
528
        return 1;
529
    }
530
    else
531
    {
532
        $error=$db->lasterror();
533
        $db->rollback();
534
        return -1;
535
    }
536
}
537
538
539
540
541
/**
542
 * Prepare array with list of tabs
543
 *
544
 * @return  array				Array of tabs to show
545
 */
546
function modules_prepare_head()
547
{
548
	global $langs, $conf, $user;
549
	$h = 0;
550
	$head = array();
551
552
	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=common";
553
	$head[$h][1] = $langs->trans("AvailableModules");
554
	$head[$h][2] = 'common';
555
	$h++;
556
557
	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=marketplace";
558
	$head[$h][1] = $langs->trans("ModulesMarketPlaces");
559
	$head[$h][2] = 'marketplace';
560
	$h++;
561
562
	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=deploy";
563
	$head[$h][1] = $langs->trans("AddExtensionThemeModuleOrOther");
564
	$head[$h][2] = 'deploy';
565
	$h++;
566
567
	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=develop";
568
	$head[$h][1] = $langs->trans("ModulesDevelopYourModule");
569
	$head[$h][2] = 'develop';
570
	$h++;
571
572
	return $head;
573
}
574
575
576
/**
577
 * Prepare array with list of tabs
578
 *
579
 * @return  array				Array of tabs to show
580
 */
581
function security_prepare_head()
582
{
583
    global $db, $langs, $conf, $user;
584
    $h = 0;
585
    $head = array();
586
587
    $head[$h][0] = DOL_URL_ROOT."/admin/security_other.php";
588
    $head[$h][1] = $langs->trans("Miscellaneous");
589
    $head[$h][2] = 'misc';
590
    $h++;
591
592
    $head[$h][0] = DOL_URL_ROOT."/admin/security.php";
593
    $head[$h][1] = $langs->trans("Passwords");
594
    $head[$h][2] = 'passwords';
595
    $h++;
596
597
    $head[$h][0] = DOL_URL_ROOT."/admin/security_file.php";
598
    $head[$h][1] = $langs->trans("Files").' ('.$langs->trans("Upload").')';
599
    $head[$h][2] = 'file';
600
    $h++;
601
602
    /*
603
    $head[$h][0] = DOL_URL_ROOT."/admin/security_file_download.php";
604
    $head[$h][1] = $langs->trans("Files").' ('.$langs->trans("Download").')';
605
    $head[$h][2] = 'filedownload';
606
    $h++;
607
	*/
608
609
    $head[$h][0] = DOL_URL_ROOT."/admin/proxy.php";
610
    $head[$h][1] = $langs->trans("ExternalAccess");
611
    $head[$h][2] = 'proxy';
612
    $h++;
613
614
    $head[$h][0] = DOL_URL_ROOT."/admin/events.php";
615
    $head[$h][1] = $langs->trans("Audit");
616
    $head[$h][2] = 'audit';
617
    $h++;
618
619
620
    // Show permissions lines
621
    $nbPerms=0;
622
    $sql = "SELECT COUNT(r.id) as nb";
623
    $sql.= " FROM ".MAIN_DB_PREFIX."rights_def as r";
624
    $sql.= " WHERE r.libelle NOT LIKE 'tou%'";    // On ignore droits "tous"
625
    $sql.= " AND entity = ".$conf->entity;
626
    $sql.= " AND bydefault = 1";
627
    if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) $sql.= " AND r.perms NOT LIKE '%_advance'";  // Hide advanced perms if option is not enabled
628
    $resql = $db->query($sql);
629
    if ($resql)
630
    {
631
    	$obj = $db->fetch_object($resql);
632
    	if ($obj) $nbPerms = $obj->nb;
633
    }
634
    else dol_print_error($db);
635
636
    $head[$h][0] = DOL_URL_ROOT."/admin/perms.php";
637
    $head[$h][1] = $langs->trans("DefaultRights");
638
    if ($nbPerms > 0) $head[$h][1].= ' <span class="badge">'.$nbPerms.'</span>';
639
    $head[$h][2] = 'default';
640
    $h++;
641
642
    return $head;
643
}
644
645
646
/**
647
 * Prepare array with list of tabs
648
 *
649
 * @return  array				Array of tabs to show
650
 */
651
function translation_prepare_head()
652
{
653
    global $langs, $conf, $user;
654
    $h = 0;
655
    $head = array();
656
657
    $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=overwrite";
658
    $head[$h][1] = $langs->trans("TranslationOverwriteKey");
659
    $head[$h][2] = 'overwrite';
660
    $h++;
661
662
    $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey";
663
    $head[$h][1] = $langs->trans("TranslationKeySearch");
664
    $head[$h][2] = 'searchkey';
665
    $h++;
666
667
    complete_head_from_modules($conf,$langs,null,$head,$h,'translation_admin');
668
669
    complete_head_from_modules($conf,$langs,null,$head,$h,'translation_admin','remove');
670
671
672
    return $head;
673
}
674
675
676
/**
677
 * Prepare array with list of tabs
678
 *
679
 * @return  array				Array of tabs to show
680
 */
681
function defaultvalues_prepare_head()
682
{
683
    global $langs, $conf, $user;
684
    $h = 0;
685
    $head = array();
686
687
    $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=createform";
688
    $head[$h][1] = $langs->trans("DefaultCreateForm");
689
    $head[$h][2] = 'createform';
690
    $h++;
691
692
    $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=filters";
693
    $head[$h][1] = $langs->trans("DefaultSearchFilters");
694
    $head[$h][2] = 'filters';
695
    $h++;
696
697
    $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=sortorder";
698
    $head[$h][1] = $langs->trans("DefaultSortOrder");
699
    $head[$h][2] = 'sortorder';
700
    $h++;
701
702
    $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=focus";
703
    $head[$h][1] = $langs->trans("DefaultFocus");
704
    $head[$h][2] = 'focus';
705
    $h++;
706
707
    /*$head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey";
708
    $head[$h][1] = $langs->trans("TranslationKeySearch");
709
    $head[$h][2] = 'searchkey';
710
    $h++;*/
711
712
    complete_head_from_modules($conf,$langs,null,$head,$h,'defaultvalues_admin');
713
714
    complete_head_from_modules($conf,$langs,null,$head,$h,'defaultvalues_admin','remove');
715
716
717
    return $head;
718
}
719
720
721
/**
722
 * 	Return list of session
723
 *
724
 *	@return		array			Array list of sessions
725
 */
726
function listOfSessions()
727
{
728
    global $conf;
729
730
    $arrayofSessions = array();
731
    // session.save_path can be returned empty so we set a default location and work from there
732
    $sessPath = '/tmp';
733
    $iniPath = ini_get("session.save_path");
734
    if ($iniPath) {
735
        $sessPath = $iniPath;
736
    }
737
    $sessPath .= '/'; // We need the trailing slash
738
    dol_syslog('admin.lib:listOfSessions sessPath='.$sessPath);
739
740
    $dh = @opendir(dol_osencode($sessPath));
741
    if ($dh)
742
    {
743
        while(($file = @readdir($dh)) !== false)
744
        {
745
            if (preg_match('/^sess_/i',$file) && $file != "." && $file != "..")
746
            {
747
                $fullpath = $sessPath.$file;
748
                if(! @is_dir($fullpath) && is_readable($fullpath))
749
                {
750
                    $sessValues = file_get_contents($fullpath);	// get raw session data
751
                    // Example of possible value
752
                    //$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";';
753
754
                    if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
755
                        (preg_match('/dol_entity\|i:'.$conf->entity.';/i',$sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i',$sessValues)) && // limit to current entity
756
                    preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
757
                    {
758
                        $tmp=explode('_', $file);
759
                        $idsess=$tmp[1];
760
                        $login = preg_match('/dol_login\|s:[0-9]+:"([A-Za-z0-9]+)"/i',$sessValues,$regs);
761
                        $arrayofSessions[$idsess]["login"] = $regs[1];
762
                        $arrayofSessions[$idsess]["age"] = time()-filectime($fullpath);
763
                        $arrayofSessions[$idsess]["creation"] = filectime($fullpath);
764
                        $arrayofSessions[$idsess]["modification"] = filemtime($fullpath);
765
                        $arrayofSessions[$idsess]["raw"] = $sessValues;
766
                    }
767
                }
768
            }
769
        }
770
        @closedir($dh);
771
    }
772
773
    return $arrayofSessions;
774
}
775
776
/**
777
 * 	Purge existing sessions
778
 *
779
 * 	@param		int		$mysessionid		To avoid to try to delete my own session
780
 * 	@return		int							>0 if OK, <0 if KO
781
 */
782
function purgeSessions($mysessionid)
783
{
784
    global $conf;
785
786
    $arrayofSessions = array();
787
    $sessPath = ini_get("session.save_path")."/";
788
    dol_syslog('admin.lib:purgeSessions mysessionid='.$mysessionid.' sessPath='.$sessPath);
789
790
    $error=0;
791
    $dh = @opendir(dol_osencode($sessPath));
792
    while(($file = @readdir($dh)) !== false)
793
    {
794
        if ($file != "." && $file != "..")
795
        {
796
            $fullpath = $sessPath.$file;
797
            if(! @is_dir($fullpath))
798
            {
799
                $sessValues = file_get_contents($fullpath);	// get raw session data
800
801
                if (preg_match('/dol_login/i',$sessValues) && // limit to dolibarr session
802
                preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i',$sessValues) && // limit to current entity
803
                preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i',$sessValues)) // limit to company name
804
                {
805
                    $tmp=explode('_', $file);
806
                    $idsess=$tmp[1];
807
                    // We remove session if it's not ourself
808
                    if ($idsess != $mysessionid)
809
                    {
810
                        $res=@unlink($fullpath);
811
                        if (! $res) $error++;
812
                    }
813
                }
814
            }
815
        }
816
    }
817
    @closedir($dh);
818
819
    if (! $error) return 1;
820
    else return -$error;
821
}
822
823
824
825
/**
826
 *  Enable a module
827
 *
828
 *  @param      string		$value      Name of module to activate
829
 *  @param      int			$withdeps   Activate/Disable also all dependencies
830
 *  @return     array      			    array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added);
831
 */
832
function activateModule($value,$withdeps=1)
833
{
834
    global $db, $modules, $langs, $conf, $mysoc;
835
836
	// Check parameters
837
	if (empty($value)) {
838
		$ret['errors'][] = 'ErrorBadParameter';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ret was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ret = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
839
		return $ret;
840
	}
841
842
    $ret=array('nbmodules'=>0, 'errors'=>array(), 'nbperms'=>0);
843
    $modName = $value;
844
    $modFile = $modName . ".class.php";
845
846
    // Loop on each directory to fill $modulesdir
847
    $modulesdir = dolGetModulesDirs();
848
849
    // Loop on each modulesdir directories
850
    $found=false;
851
    foreach ($modulesdir as $dir)
852
    {
853
        if (file_exists($dir.$modFile))
854
        {
855
            $found=@include_once $dir.$modFile;
856
            if ($found) break;
857
        }
858
    }
859
860
    $objMod = new $modName($db);
861
862
    // Test if PHP version ok
863
    $verphp=versionphparray();
864
    $vermin=isset($objMod->phpmin)?$objMod->phpmin:0;
865
	if (is_array($vermin) && versioncompare($verphp, $vermin) < 0) {
866
		$ret['errors'][] = $langs->trans("ErrorModuleRequirePHPVersion", versiontostring($vermin));
867
		return $ret;
868
	}
869
870
    // Test if Dolibarr version ok
871
    $verdol=versiondolibarrarray();
872
    $vermin=isset($objMod->need_dolibarr_version)?$objMod->need_dolibarr_version:0;
873
    //print 'version: '.versioncompare($verdol,$vermin).' - '.join(',',$verdol).' - '.join(',',$vermin);exit;
874
	if (is_array($vermin) && versioncompare($verdol, $vermin) < 0) {
875
		$ret['errors'][] = $langs->trans("ErrorModuleRequireDolibarrVersion", versiontostring($vermin));
876
		return $ret;
877
	}
878
879
	// Test if javascript requirement ok
880
	if (!empty($objMod->need_javascript_ajax) && empty($conf->use_javascript_ajax)) {
881
		$ret['errors'][] = $langs->trans("ErrorModuleRequireJavascript");
882
		return $ret;
883
	}
884
885
	$const_name = $objMod->const_name;
886
	if(!empty($conf->global->$const_name)){
887
        return $ret;
888
    }
889
890
    $result=$objMod->init();    // Enable module
891
892
    if ($result <= 0)
893
    {
894
        $ret['errors'][]=$objMod->error;
895
    }
896
    else
897
    {
898
        if ($withdeps)
899
        {
900
            if (isset($objMod->depends) && is_array($objMod->depends) && ! empty($objMod->depends))
901
            {
902
                // Activation of modules this module depends on
903
                // this->depends may be array('modModule1', 'mmodModule2') or array('always'=>"modModule1", 'FR'=>'modModule2')
904
                foreach ($objMod->depends as $key => $modulestring)
905
                {
906
                    if ((! is_numeric($key)) && $key != 'always' && $key != $mysoc->country_code)
907
                    {
908
                        dol_syslog("We are not concerned by dependency with key=".$key." because our country is ".$mysoc->country_code);
909
                        continue;
910
                    }
911
                	$activate = false;
912
                	foreach ($modulesdir as $dir)
913
                	{
914
                		if (file_exists($dir.$modulestring.".class.php"))
915
                		{
916
                			$resarray = activateModule($modulestring);
917
    						if (empty($resarray['errors'])){
918
    						    $activate = true;
919
                            }else{
920
    						    foreach ($resarray['errors'] as $errorMessage){
921
                                    dol_syslog($errorMessage, LOG_ERR);
922
                                }
923
                            }
924
    						break;
925
                		}
926
                	}
927
928
    				if ($activate)
929
    				{
930
    				    $ret['nbmodules']+=$resarray['nbmodules'];
0 ignored issues
show
Bug introduced by
The variable $resarray does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
931
    				    $ret['nbperms']+=$resarray['nbperms'];
932
    				}
933
    				else
934
    				{
935
    				    $ret['errors'][] = $langs->trans('activateModuleDependNotSatisfied', $objMod->name, $modulestring);
936
    				}
937
                }
938
            }
939
940
            if (isset($objMod->conflictwith) && is_array($objMod->conflictwith) && ! empty($objMod->conflictwith))
941
            {
942
                // Desactivation des modules qui entrent en conflit
943
                $num = count($objMod->conflictwith);
944
                for ($i = 0; $i < $num; $i++)
945
                {
946
                	foreach ($modulesdir as $dir)
947
                	{
948
                		if (file_exists($dir.$objMod->conflictwith[$i].".class.php"))
949
                		{
950
                			unActivateModule($objMod->conflictwith[$i],0);
951
                		}
952
                	}
953
                }
954
            }
955
        }
956
    }
957
958
    if (! count($ret['errors']))
959
    {
960
        $ret['nbmodules']++;
961
        $ret['nbperms']+=count($objMod->rights);
962
    }
963
964
    return $ret;
965
}
966
967
968
/**
969
 *  Disable a module
970
 *
971
 *  @param      string		$value               Nom du module a desactiver
972
 *  @param      int			$requiredby          1=Desactive aussi modules dependants
973
 *  @return     string     				         Error message or '';
974
 */
975
function unActivateModule($value, $requiredby=1)
976
{
977
    global $db, $modules, $conf;
978
979
    // Check parameters
980
    if (empty($value)) return 'ErrorBadParameter';
981
982
    $ret='';
983
    $modName = $value;
984
    $modFile = $modName . ".class.php";
985
986
    // Loop on each directory to fill $modulesdir
987
    $modulesdir = dolGetModulesDirs();
988
989
    // Loop on each modulesdir directories
990
    $found=false;
991
    foreach ($modulesdir as $dir)
992
    {
993
        if (file_exists($dir.$modFile))
994
        {
995
            $found=@include_once $dir.$modFile;
996
            if ($found) break;
997
        }
998
    }
999
1000
    if ($found)
1001
    {
1002
        $objMod = new $modName($db);
1003
        $result=$objMod->remove();
1004
        if ($result <= 0) $ret=$objMod->error;
1005
    }
1006
    else
1007
    {
1008
        //print $dir.$modFile;
1009
    	// 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
1010
        include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
1011
    	$genericMod = new DolibarrModules($db);
1012
        $genericMod->name=preg_replace('/^mod/i','',$modName);
1013
        $genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName));
1014
        $genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName));
1015
        dol_syslog("modules::unActivateModule Failed to find module file, we use generic function with name " . $modName);
1016
        $genericMod->_remove(array());
1017
    }
1018
1019
    // Desactivation des modules qui dependent de lui
1020
    if (! $ret && $requiredby)
1021
    {
1022
        $countrb=count($objMod->requiredby);
0 ignored issues
show
Bug introduced by
The variable $objMod does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1023
        for ($i = 0; $i < $countrb; $i++)
1024
        {
1025
            //var_dump($objMod->requiredby[$i]);
1026
            unActivateModule($objMod->requiredby[$i]);
1027
        }
1028
    }
1029
1030
    return $ret;
1031
}
1032
1033
1034
/**
1035
 *  Add external modules to list of dictionaries.
1036
 *  Addition is done into var $taborder, $tabname, etc... that are passed with pointers.
1037
 *
1038
 * 	@param		array		$taborder			Taborder
1039
 * 	@param		array		$tabname			Tabname
1040
 * 	@param		array		$tablib				Tablib
1041
 * 	@param		array		$tabsql				Tabsql
1042
 * 	@param		array		$tabsqlsort			Tabsqlsort
1043
 * 	@param		array		$tabfield			Tabfield
1044
 * 	@param		array		$tabfieldvalue		Tabfieldvalue
1045
 * 	@param		array		$tabfieldinsert		Tabfieldinsert
1046
 * 	@param		array		$tabrowid			Tabrowid
1047
 * 	@param		array		$tabcond			Tabcond
1048
 * 	@param		array		$tabhelp			Tabhelp
1049
 *  @param		array		$tabfieldcheck		Tabfieldcheck
1050
 * 	@return		int			1
1051
 */
1052
function complete_dictionary_with_modules(&$taborder,&$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond,&$tabhelp,&$tabfieldcheck)
1053
{
1054
    global $db, $modules, $conf, $langs;
1055
1056
    // Search modules
1057
	$modulesdir = dolGetModulesDirs();
1058
    $i = 0; // is a sequencer of modules found
1059
    $j = 0; // j is module number. Automatically affected if module number not defined.
1060
1061
    foreach ($modulesdir as $dir)
1062
    {
1063
    	// Load modules attributes in arrays (name, numero, orders) from dir directory
1064
    	//print $dir."\n<br>";
1065
    	dol_syslog("Scan directory ".$dir." for modules");
1066
        $handle=@opendir(dol_osencode($dir));
1067
        if (is_resource($handle))
1068
        {
1069
            while (($file = readdir($handle))!==false)
1070
            {
1071
                //print "$i ".$file."\n<br>";
1072
                if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod'  && substr($file, dol_strlen($file) - 10) == '.class.php')
1073
                {
1074
                    $modName = substr($file, 0, dol_strlen($file) - 10);
1075
1076
                    if ($modName)
1077
                    {
1078
                        include_once $dir.$file;
1079
                        $objMod = new $modName($db);
1080
1081
                        if ($objMod->numero > 0)
1082
                        {
1083
                            $j = $objMod->numero;
1084
                        }
1085
                        else
1086
                        {
1087
                            $j = 1000 + $i;
1088
                        }
1089
1090
                        $modulequalified=1;
1091
1092
                        // We discard modules according to features level (PS: if module is activated we always show it)
1093
                        $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
1094
                        if ($objMod->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
1095
                        if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
1096
                        //If module is not activated disqualified
1097
                        if (empty($conf->global->$const_name)) $modulequalified=0;
1098
1099
                        if ($modulequalified)
1100
                        {
1101
							// Load languages files of module
1102
							if (isset($objMod->langfiles) && is_array($objMod->langfiles)) {
1103
								foreach ($objMod->langfiles as $langfile) {
1104
									$langs->load($langfile);
1105
								}
1106
							}
1107
1108
                            // Complete the arrays &$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond
1109
                            if (empty($objMod->dictionaries) && ! empty($objMod->dictionnaries)) $objMod->dictionaries=$objMod->dictionnaries;		// For backward compatibility
1110
1111
                            if (! empty($objMod->dictionaries))
1112
                            {
1113
                                //var_dump($objMod->dictionaries['tabname']);
1114
                                $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp=0;
1115
                                foreach($objMod->dictionaries['tabname'] as $val)        { $nbtabname++; $taborder[] = max($taborder)+1; $tabname[] = $val; }		// Position
1116
                                foreach($objMod->dictionaries['tablib'] as $val)         { $nbtablib++; $tablib[] = $val; }
1117
                                foreach($objMod->dictionaries['tabsql'] as $val)         { $nbtabsql++; $tabsql[] = $val; }
1118
                                foreach($objMod->dictionaries['tabsqlsort'] as $val)     { $nbtabsqlsort++; $tabsqlsort[] = $val; }
1119
                                foreach($objMod->dictionaries['tabfield'] as $val)       { $nbtabfield++; $tabfield[] = $val; }
1120
                                foreach($objMod->dictionaries['tabfieldvalue'] as $val)  { $nbtabfieldvalue++; $tabfieldvalue[] = $val; }
1121
                                foreach($objMod->dictionaries['tabfieldinsert'] as $val) { $nbtabfieldinsert++; $tabfieldinsert[] = $val; }
1122
                                foreach($objMod->dictionaries['tabrowid'] as $val)       { $nbtabrowid++; $tabrowid[] = $val; }
1123
                                foreach($objMod->dictionaries['tabcond'] as $val)        { $nbtabcond++; $tabcond[] = $val; }
1124
                                if (! empty($objMod->dictionaries['tabhelp']))       foreach($objMod->dictionaries['tabhelp'] as $val)       { $nbtabhelp++; $tabhelp[] = $val; }
1125
                                if (! empty($objMod->dictionaries['tabfieldcheck'])) foreach($objMod->dictionaries['tabfieldcheck'] as $val) { $nbtabfieldcheck++; $tabfieldcheck[] = $val; }
1126
1127
                                if ($nbtabname != $nbtablib || $nbtablib != $nbtabsql || $nbtabsql != $nbtabsqlsort)
1128
                                {
1129
                                    print 'Error in descriptor of module '.$const_name.'. Array ->dictionaries has not same number of record for key "tabname", "tablib", "tabsql" and "tabsqlsort"';
1130
                                    //print "$const_name: $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp\n";
1131
                                }
1132
                                else
1133
                                {
1134
                                	$taborder[] = 0;	// Add an empty line
1135
                                }
1136
                            }
1137
1138
                            $j++;
1139
                            $i++;
1140
                        }
1141
                        else dol_syslog("Module ".get_class($objMod)." not qualified");
1142
                    }
1143
                }
1144
            }
1145
            closedir($handle);
1146
        }
1147
        else
1148
        {
1149
            dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
1150
        }
1151
    }
1152
1153
    return 1;
1154
}
1155
1156
/**
1157
 *  Activate external modules mandatory when country is country_code
1158
 *
1159
 * 	@param		string		$country_code	CountryCode
1160
 * 	@return		int			1
1161
 */
1162
function activateModulesRequiredByCountry($country_code)
1163
{
1164
	global $db, $conf, $langs;
1165
1166
	$modulesdir = dolGetModulesDirs();
1167
1168
	foreach ($modulesdir as $dir)
1169
	{
1170
		// Load modules attributes in arrays (name, numero, orders) from dir directory
1171
		dol_syslog("Scan directory ".$dir." for modules");
1172
		$handle=@opendir(dol_osencode($dir));
1173
		if (is_resource($handle))
1174
		{
1175
			while (($file = readdir($handle))!==false)
1176
			{
1177
				if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod'  && substr($file, dol_strlen($file) - 10) == '.class.php')
1178
				{
1179
					$modName = substr($file, 0, dol_strlen($file) - 10);
1180
1181
					if ($modName)
1182
					{
1183
						include_once $dir.$file;
1184
						$objMod = new $modName($db);
1185
1186
						$modulequalified=1;
1187
1188
						// We discard modules according to features level (PS: if module is activated we always show it)
1189
						$const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
1190
1191
						if ($objMod->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified=0;
1192
						if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified=0;
1193
						if(!empty($conf->global->$const_name)) $modulequalified=0; // already activated
1194
1195
						if ($modulequalified)
1196
						{
1197
							// Load languages files of module
1198
							if (isset($objMod->automatic_activation) && is_array($objMod->automatic_activation) && isset($objMod->automatic_activation[$country_code]))
1199
							{
1200
								activateModule($modName);
1201
1202
								setEventMessage($objMod->automatic_activation[$country_code],'warnings');
1203
							}
1204
1205
						}
1206
						else dol_syslog("Module ".get_class($objMod)." not qualified");
1207
					}
1208
				}
1209
			}
1210
			closedir($handle);
1211
		}
1212
		else
1213
		{
1214
			dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
1215
		}
1216
	}
1217
1218
	return 1;
1219
}
1220
1221
/**
1222
 *  Add external modules to list of contact element
1223
 *
1224
 * 	@param		array		$elementList			elementList
1225
 * 	@return		int			1
1226
 */
1227
function complete_elementList_with_modules(&$elementList)
1228
{
1229
    global $db, $modules, $conf, $langs;
1230
1231
    // Search modules
1232
    $filename = array();
1233
    $modules = array();
1234
    $orders = array();
1235
    $categ = array();
1236
    $dirmod = array();
1237
1238
    $i = 0; // is a sequencer of modules found
1239
    $j = 0; // j is module number. Automatically affected if module number not defined.
1240
1241
    $modulesdir = dolGetModulesDirs();
1242
1243
    foreach ($modulesdir as $dir)
1244
    {
1245
    	// Load modules attributes in arrays (name, numero, orders) from dir directory
1246
    	//print $dir."\n<br>";
1247
    	dol_syslog("Scan directory ".$dir." for modules");
1248
        $handle=@opendir(dol_osencode($dir));
1249
        if (is_resource($handle))
1250
        {
1251
            while (($file = readdir($handle))!==false)
1252
            {
1253
                //print "$i ".$file."\n<br>";
1254
                if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod'  && substr($file, dol_strlen($file) - 10) == '.class.php')
1255
                {
1256
                    $modName = substr($file, 0, dol_strlen($file) - 10);
1257
1258
                    if ($modName)
1259
                    {
1260
                        include_once $dir.$file;
1261
                        $objMod = new $modName($db);
1262
1263
                        if ($objMod->numero > 0)
1264
                        {
1265
                            $j = $objMod->numero;
1266
                        }
1267
                        else
1268
                        {
1269
                            $j = 1000 + $i;
1270
                        }
1271
1272
                        $modulequalified=1;
1273
1274
                        // We discard modules according to features level (PS: if module is activated we always show it)
1275
                        $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
1276
                        if ($objMod->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
1277
                        if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
1278
                        //If module is not activated disqualified
1279
                        if (empty($conf->global->$const_name)) $modulequalified=0;
1280
1281
                        if ($modulequalified)
1282
                        {
1283
							// Load languages files of module
1284
                            if (isset($objMod->langfiles) && is_array($objMod->langfiles))
1285
                            {
1286
                             	foreach($objMod->langfiles as $langfile)
1287
                              	{
1288
                               		$langs->load($langfile);
1289
                               	}
1290
                           	}
1291
1292
                            $modules[$i] = $objMod;
1293
                            $filename[$i]= $modName;
1294
                            $orders[$i]  = $objMod->family."_".$j;   // Sort on family then module number
1295
                            $dirmod[$i] = $dir;
1296
                            //print "x".$modName." ".$orders[$i]."\n<br>";
1297
1298
                            if (! empty($objMod->module_parts['contactelement']))
1299
                            {
1300
                            	$elementList[$objMod->name] = $langs->trans($objMod->name);
1301
                            }
1302
1303
                            $j++;
1304
                            $i++;
1305
                        }
1306
                        else dol_syslog("Module ".get_class($objMod)." not qualified");
1307
                    }
1308
                }
1309
            }
1310
            closedir($handle);
1311
        }
1312
        else
1313
        {
1314
            dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
1315
        }
1316
    }
1317
1318
    return 1;
1319
}
1320
1321
/**
1322
 *	Show array with constants to edit
1323
 *
1324
 *	@param	array	$tableau		Array of constants
1325
 *	@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
1326
 *  @param  string  $helptext       Help
1327
 *	@return	void
1328
 */
1329
function form_constantes($tableau, $strictw3c=0, $helptext='')
1330
{
1331
    global $db,$bc,$langs,$conf,$_Avery_Labels;
1332
1333
    $form = new Form($db);
1334
1335
    if (! empty($strictw3c) && $strictw3c == 1) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1336
1337
    print '<table class="noborder" width="100%">';
1338
    print '<tr class="liste_titre">';
1339
    print '<td class="titlefield">'.$langs->trans("Description").'</td>';
1340
    print '<td>';
1341
    $text = $langs->trans("Value");
1342
    print $form->textwithpicto($text, $helptext, 1, 'help', '', 0, 2, 'idhelptext');
1343
    print '</td>';
1344
    if (empty($strictw3c)) print '<td align="center" width="80">'.$langs->trans("Action").'</td>';
1345
    print "</tr>\n";
1346
    $var=true;
1347
1348
    $listofparam=array();
1349
    foreach($tableau as $const)	// Loop on each param
1350
    {
1351
        $sql = "SELECT ";
1352
        $sql.= "rowid";
1353
        $sql.= ", ".$db->decrypt('name')." as name";
1354
        $sql.= ", ".$db->decrypt('value')." as value";
1355
        $sql.= ", type";
1356
        $sql.= ", note";
1357
        $sql.= " FROM ".MAIN_DB_PREFIX."const";
1358
        $sql.= " WHERE ".$db->decrypt('name')." = '".$const."'";
1359
        $sql.= " AND entity IN (0, ".$conf->entity.")";
1360
        $sql.= " ORDER BY name ASC, entity DESC";
1361
        $result = $db->query($sql);
1362
1363
        dol_syslog("List params", LOG_DEBUG);
1364
        if ($result)
1365
        {
1366
            $obj = $db->fetch_object($result);	// Take first result of select
1367
1368
1369
            // For avoid warning in strict mode
1370
            if (empty($obj)) {
1371
            	$obj = (object) array('rowid'=>'','name'=>'','value'=>'','type'=>'','note'=>'');
1372
            }
1373
1374
            if (empty($strictw3c)) print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1375
1376
            print '<tr class="oddeven">';
1377
1378
            // Show constant
1379
            print '<td>';
1380
            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1381
            print '<input type="hidden" name="action" value="update">';
1382
            print '<input type="hidden" name="rowid'.(empty($strictw3c)?'':'[]').'" value="'.$obj->rowid.'">';
1383
            print '<input type="hidden" name="constname'.(empty($strictw3c)?'':'[]').'" value="'.$const.'">';
1384
            print '<input type="hidden" name="constnote'.(empty($strictw3c)?'':'[]').'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">';
1385
1386
            print $langs->trans('Desc'.$const);
1387
1388
            if ($const == 'ADHERENT_MAILMAN_URL')
1389
            {
1390
                print '. '.$langs->trans("Example").': <a href="#" id="exampleclick1">'.img_down().'</a><br>';
1391
                //print 'http://lists.exampe.com/cgi-bin/mailman/admin/%LISTE%/members?adminpw=%MAILMAN_ADMINPW%&subscribees=%EMAIL%&send_welcome_msg_to_this_batch=1';
1392
                print '<div id="example1" class="hidden">';
1393
                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';
1394
                print '</div>';
1395
            }
1396
            if ($const == 'ADHERENT_MAILMAN_UNSUB_URL')
1397
            {
1398
                print '. '.$langs->trans("Example").': <a href="#" id="exampleclick2">'.img_down().'</a><br>';
1399
                print '<div id="example2" class="hidden">';
1400
                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';
1401
                print '</div>';
1402
                //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
1403
            }
1404
            if ($const == 'ADHERENT_MAILMAN_LISTS')
1405
            {
1406
            	print '. '.$langs->trans("Example").': <a href="#" id="exampleclick3">'.img_down().'</a><br>';
1407
            	print '<div id="example3" class="hidden">';
1408
            	print 'mymailmanlist<br>';
1409
            	print 'mymailmanlist1,mymailmanlist2<br>';
1410
            	print 'TYPE:Type1:mymailmanlist1,TYPE:Type2:mymailmanlist2<br>';
1411
            	if ($conf->categorie->enabled) print 'CATEG:Categ1:mymailmanlist1,CATEG:Categ2:mymailmanlist2<br>';
1412
            	print '</div>';
1413
            	//print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%';
1414
            }
1415
1416
            print "</td>\n";
1417
1418
            // Value
1419
            if ($const == 'ADHERENT_CARD_TYPE' || $const == 'ADHERENT_ETIQUETTE_TYPE')
1420
            {
1421
                print '<td>';
1422
                // List of possible labels (defined into $_Avery_Labels variable set into format_cards.lib.php)
1423
                require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
1424
                $arrayoflabels=array();
1425
                foreach(array_keys($_Avery_Labels) as $codecards)
1426
                {
1427
                    $arrayoflabels[$codecards]=$_Avery_Labels[$codecards]['name'];
1428
                }
1429
                print $form->selectarray('constvalue'.(empty($strictw3c)?'':'[]'),$arrayoflabels,($obj->value?$obj->value:'CARD'),1,0,0);
1430
                print '<input type="hidden" name="consttype" value="yesno">';
1431
                print '</td>';
1432
            }
1433
            else
1434
            {
1435
                print '<td>';
1436
                if (in_array($const,array('ADHERENT_CARD_TEXT','ADHERENT_CARD_TEXT_RIGHT','ADHERENT_ETIQUETTE_TEXT')))
1437
                {
1438
                    print '<textarea class="flat" name="constvalue'.(empty($strictw3c)?'':'[]').'" cols="50" rows="5" wrap="soft">'."\n";
1439
                    print $obj->value;
1440
                    print "</textarea>\n";
1441
                    print '<input type="hidden" name="consttype" value="texte">';
1442
                }
1443
                else if (in_array($const,array('ADHERENT_AUTOREGISTER_NOTIF_MAIL','ADHERENT_AUTOREGISTER_MAIL','ADHERENT_MAIL_VALID','ADHERENT_MAIL_COTIS','ADHERENT_MAIL_RESIL')))
1444
                {
1445
                    require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1446
                    $doleditor=new DolEditor('constvalue_'.$const.(empty($strictw3c)?'':'[]'),$obj->value,'',160,'dolibarr_notes','',false,false,$conf->fckeditor->enabled,ROWS_5,'90%');
1447
                    $doleditor->Create();
1448
                    print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="texte">';
1449
                }
1450
                else if ($obj->type == 'yesno')
1451
                {
1452
                    print $form->selectyesno('constvalue'.(empty($strictw3c)?'':'[]'),$obj->value,1);
1453
                    print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="yesno">';
1454
                }
1455
                else
1456
                {
1457
                    print '<input type="text" class="flat" size="48" name="constvalue'.(empty($strictw3c)?'':'[]').'" value="'.dol_escape_htmltag($obj->value).'">';
1458
                    print '<input type="hidden" name="consttype'.(empty($strictw3c)?'':'[]').'" value="chaine">';
1459
                }
1460
                print '</td>';
1461
            }
1462
            // Submit
1463
            if (empty($strictw3c))
1464
            {
1465
            	print '<td align="center">';
1466
            	print '<input type="submit" class="button" value="'.$langs->trans("Update").'" name="Button">';
1467
	            print "</td>";
1468
            }
1469
    	    print "</tr>\n";
1470
            if (empty($strictw3c)) print "</form>\n";
1471
        }
1472
    }
1473
    print '</table>';
1474
1475
    if (! empty($strictw3c) && $strictw3c == 1)
1476
    {
1477
    	print '<div align="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
1478
    	print "</form>\n";
1479
    }
1480
}
1481
1482
1483
/**
1484
 *	Show array with constants to edit
1485
 *
1486
 *	@param	array	$modules		Array of all modules
1487
 *	@return	string					HTML string with warning
1488
 */
1489
function showModulesExludedForExternal($modules)
1490
{
1491
	global $conf,$langs;
1492
1493
	$text=$langs->trans("OnlyFollowingModulesAreOpenedToExternalUsers");
1494
	$listofmodules=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL);
1495
	$i=0;
1496
	if (!empty($modules)) {
1497
		foreach($modules as $module)
1498
		{
1499
			$moduleconst=$module->const_name;
1500
			$modulename=strtolower($module->name);
1501
			//print 'modulename='.$modulename;
1502
1503
			//if (empty($conf->global->$moduleconst)) continue;
1504
			if (! in_array($modulename,$listofmodules)) continue;
1505
			//var_dump($modulename.' - '.$langs->trans('Module'.$module->numero.'Name'));
1506
1507
			if ($i > 0) $text.=', ';
1508
			else $text.=' ';
1509
			$i++;
1510
			$text .= $langs->trans('Module'.$module->numero.'Name');
1511
		}
1512
	}
1513
	return $text;
1514
}
1515
1516
1517
/**
1518
 *	Add document model used by doc generator
1519
 *
1520
 *	@param		string	$name			Model name
1521
 *	@param		string	$type			Model type
1522
 *	@param		string	$label			Model label
1523
 *	@param		string	$description	Model description
1524
 *	@return		int						<0 if KO, >0 if OK
1525
 */
1526
function addDocumentModel($name, $type, $label='', $description='')
1527
{
1528
	global $db, $conf;
1529
1530
	$db->begin();
1531
1532
    $sql = "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity, libelle, description)";
1533
    $sql.= " VALUES ('".$db->escape($name)."','".$type."',".$conf->entity.", ";
1534
    $sql.= ($label?"'".$db->escape($label)."'":'null').", ";
1535
    $sql.= (! empty($description)?"'".$db->escape($description)."'":"null");
1536
    $sql.= ")";
1537
1538
    dol_syslog("admin.lib::addDocumentModel", LOG_DEBUG);
1539
	$resql=$db->query($sql);
1540
	if ($resql)
1541
	{
1542
		$db->commit();
1543
		return 1;
1544
	}
1545
	else
1546
	{
1547
		dol_print_error($db);
1548
		$db->rollback();
1549
		return -1;
1550
	}
1551
}
1552
1553
/**
1554
 *	Delete document model used by doc generator
1555
 *
1556
 *	@param		string	$name			Model name
1557
 *	@param		string	$type			Model type
1558
 *	@return		int						<0 if KO, >0 if OK
1559
 */
1560
function delDocumentModel($name, $type)
1561
{
1562
	global $db, $conf;
1563
1564
	$db->begin();
1565
1566
	$sql = "DELETE FROM ".MAIN_DB_PREFIX."document_model";
1567
	$sql.= " WHERE nom = '".$db->escape($name)."'";
1568
	$sql.= " AND type = '".$type."'";
1569
	$sql.= " AND entity = ".$conf->entity;
1570
1571
	dol_syslog("admin.lib::delDocumentModel", LOG_DEBUG);
1572
	$resql=$db->query($sql);
1573
	if ($resql)
1574
	{
1575
		$db->commit();
1576
		return 1;
1577
	}
1578
	else
1579
	{
1580
		dol_print_error($db);
1581
		$db->rollback();
1582
		return -1;
1583
	}
1584
}
1585
1586
1587
/**
1588
 *	Return the php_info into an array
1589
 *
1590
 *	@return		array		Array with PHP infos
1591
 */
1592
function phpinfo_array()
1593
{
1594
	ob_start();
1595
	phpinfo();
1596
	$info_arr = array();
1597
	$info_lines = explode("\n", strip_tags(ob_get_clean(), "<tr><td><h2>"));	// end of ob_start()
1598
	$cat = "General";
1599
	foreach($info_lines as $line)
1600
	{
1601
		// new cat?
1602
		preg_match("~<h2>(.*)</h2>~", $line, $title) ? $cat = $title[1] : null;
1603
		if(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
1604
		{
1605
			$info_arr[trim($cat)][trim($val[1])] = $val[2];
1606
		}
1607
		elseif(preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val))
1608
		{
1609
			$info_arr[trim($cat)][trim($val[1])] = array("local" => $val[2], "master" => $val[3]);
1610
		}
1611
	}
1612
	return $info_arr;
1613
}
1614
1615
/**
1616
 *  Return array head with list of tabs to view object informations.
1617
 *
1618
 *  @return	array   	    		    head array with tabs
1619
 */
1620
function company_admin_prepare_head()
1621
{
1622
	global $langs, $conf, $user;
1623
1624
	$h = 0;
1625
	$head = array();
1626
1627
	$head[$h][0] = DOL_URL_ROOT."/admin/company.php";
1628
	$head[$h][1] = $langs->trans("Company");
1629
	$head[$h][2] = 'company';
1630
	$h++;
1631
1632
	$head[$h][0] = DOL_URL_ROOT."/admin/accountant.php";
1633
	$head[$h][1] = $langs->trans("Accountant");
1634
	$head[$h][2] = 'accountant';
1635
	$h++;
1636
1637
	complete_head_from_modules($conf,$langs,null,$head,$h,'company_admin','remove');
1638
1639
	return $head;
1640
}
1641
1642
/**
1643
 *  Return array head with list of tabs to view object informations.
1644
 *
1645
 *  @return	array   	    		    head array with tabs
1646
 */
1647
function email_admin_prepare_head()
1648
{
1649
	global $langs, $conf, $user;
1650
1651
	$h = 0;
1652
	$head = array();
1653
1654
	if ($user->admin && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates'))
1655
	{
1656
		$head[$h][0] = DOL_URL_ROOT."/admin/mails.php";
1657
		$head[$h][1] = $langs->trans("OutGoingEmailSetup");
1658
		$head[$h][2] = 'common';
1659
		$h++;
1660
1661
		if ($conf->mailing->enabled)
1662
		{
1663
			$head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php";
1664
			$head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing");
1665
			$head[$h][2] = 'common_emailing';
1666
			$h++;
1667
		}
1668
	}
1669
1670
	$head[$h][0] = DOL_URL_ROOT."/admin/mails_templates.php";
1671
	$head[$h][1] = $langs->trans("DictionaryEMailTemplates");
1672
	$head[$h][2] = 'templates';
1673
	$h++;
1674
1675
	if ($conf->global->MAIN_FEATURES_LEVEL >= 1)
1676
	{
1677
		$head[$h][0] = DOL_URL_ROOT."/admin/mails_senderprofile_list.php";
1678
		$head[$h][1] = $langs->trans("EmailSenderProfiles");
1679
		$head[$h][2] = 'senderprofiles';
1680
		$h++;
1681
	}
1682
1683
	complete_head_from_modules($conf,$langs,null,$head,$h,'email_admin','remove');
1684
1685
	return $head;
1686
}
1687
1688
1689