getFData : try to catch error casting data to string
[ldapsaisie.git] / public_html / includes / functions.php
1 <?php
2 /*******************************************************************************
3  * Copyright (C) 2007 Easter-eggs
4  * http://ldapsaisie.labs.libre-entreprise.org
5  *
6  * Author: See AUTHORS file in top-level directory.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
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, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 ******************************************************************************/
22
23 /**
24  * Construction d'une chaine formatée
25  *
26  * Cette fonction retourne la valeur d'une chaine formatée selon le format
27  * et les données passés en paramètre.
28  *
29  * @author Benjamin Renard <brenard@easter-eggs.com>
30  *
31  * @param[in] $format string Format de la chaine
32  * @param[in] $data mixed Les données pour composés la chaine
33  *                    Ce paramètre peut être un tableau de string, une string,
34  *                    une tableau d'objet ou un objet.
35  * @param[in] $meth string Le nom de la methode de/des objet(s) à appeler pour
36  *                         obtenir la valeur de remplacement dans la chaine formatée.
37  * 
38  * @retval string La chaine formatée
39  */
40 function getFData($format,$data,$meth=NULL) {
41   $unique=false;
42   /*
43    * Format : %{[key name][:A][:B][! ou _][~]}
44    *
45    * Extracted fields
46    * - 1 : key name
47    * - 2 : :A
48    * - 3 : A
49    * - 4 : :B
50    * - 5 : B
51    * - 6 : "-"
52    * - 7 : ! or _
53    * - 8 : ~
54    */
55   $expr="%[{(]([A-Za-z0-9]+)(\:(-?[0-9])+)?(\:(-?[0-9]+))?(-)?(\!|\_)?(~)?[})]";
56   if(!is_array($format)) {
57     $format=array($format);
58     $unique=true;
59   }
60   for($i=0;$i<count($format);$i++) {
61     if(is_array($data)) {
62       if ($meth==NULL) {
63         while (ereg($expr,$format[$i],$ch)) {
64           if (is_array($data[$ch[1]])) {
65             $val = $data[$ch[1]][0];
66           }
67           else {
68             $val = $data[$ch[1]];
69           }
70           $val=_getFData_extractAndModify($val,$ch);
71           $format[$i]=str_replace($ch[0],$val,$format[$i]);
72         }
73       }
74       else {
75         while (ereg($expr,$format[$i],$ch)) {
76           if (method_exists($data[$ch[1]],$meth)) {
77             $value = $data[$ch[1]] -> $meth();
78             if (is_array($value)) {
79               $value = $value[0];
80             }
81             $value=_getFData_extractAndModify($value,$ch);
82             $format[$i]=str_replace($ch[0],$value,$format[$i]);
83           }
84           else {
85             LSerror :: addErrorCode('fct_getFData_01',array('meth' => $meth,'obj' => $ch[1]));
86             break;
87           }
88         }
89       }
90     }
91     elseif (is_object($data)) {
92       if ($meth==NULL) {
93         while (ereg($expr,$format[$i],$ch)) {
94           $value = $data -> $ch[1];
95           if (is_array($value)) {
96             $value = $value[0];
97           }
98           $value=_getFData_extractAndModify($value,$ch);
99           $format[$i]=str_replace($ch[0],$value,$format[$i]);
100         }
101       }
102       else {
103         while (ereg($expr,$format[$i],$ch)) {
104           if (method_exists($data,$meth)) {
105             $value = $data -> $meth($ch[1]);
106             if (is_array($value)) {
107               $value = $value[0];
108             }
109             $value=_getFData_extractAndModify($value,$ch);
110             $format[$i]=str_replace($ch[0],$value,$format[$i]);
111           }
112           else {
113             LSerror :: addErrorCode(0,getFData(_("Function 'getFData' : The method %{meth} of the object %{obj} doesn't exist."),array('meth' => $meth,'obj' => get_class($data))));
114             break;
115           }
116         }
117       }
118     }
119     else {
120       while (ereg($expr,$format[$i],$ch)) {
121         $val=_getFData_extractAndModify($data,$ch);
122         $format[$i]=str_replace($ch[0],$val,$format[$i]);
123       }
124     }
125   }
126   if($unique) {
127     return $format[0];
128   }
129   return $format;
130 }
131
132 function _getFData_extractAndModify($data,$ch) {
133   if($ch[3]) {
134     if ($ch[5]) {
135       if ($ch[6]) {
136         if ($ch[3]<0) {
137           $s=strlen((string)$data)-(-1*$ch[3])-$ch[5];
138           $l=$ch[5];
139         }
140         else {
141           $s=$ch[3]-$ch[5];
142           $l=$ch[5];
143           if ($s<0) {
144             $l=$l-(-1*$s);
145             $s=0;
146           }
147         }
148       }
149       else {
150         $s=$ch[3];
151         $l=$ch[5];
152       }
153     }
154     else if ($ch[5]==0) {
155       if ($ch[3]<0) {
156         $s=strlen((string)$data)-(-1*$ch[3]);
157         $l=strlen((string)$data);
158       }
159       else {
160         $s=$ch[3];
161         $l=strlen((string)$data);
162       }
163     }
164     else {
165       $s=0;
166       $l=$ch[3];
167     }
168     $val=substr((string)$data,$s,$l);
169   }
170   else {
171     try {
172       $val=strval($data);
173     }
174     catch (Exception $e) {
175       $val=_('[not string value]');
176     }
177   }
178
179   # Without Accent
180   if ($ch[8]) {
181     $val = withoutAccents($val);
182   }
183  
184   # Upper / Lower case
185   if ($ch[7]=="!") {
186     $val=strtoupper($val);
187   }
188   elseif ($ch[7]=='_') {
189     $val=strtolower($val);
190   }
191
192   return $val;
193 }
194
195 function getFieldInFormat($format) {
196   $fields=array();
197   $expr="%[{(]([A-Za-z0-9]+)(\:(-?[0-9])+)?(\:(-?[0-9]+))?(-)?(\!|\_)?(~)?[})]";
198   while (ereg($expr,$format,$ch)) {
199     $fields[]=$ch[1];
200     $format=str_replace($ch[0],'',$format);
201   }
202   return $fields;
203 }
204
205 function loadDir($dir,$regexpr='^.*\.php$') {
206   if ($handle = opendir($dir)) {
207     while (false !== ($file = readdir($handle))) {
208       if (ereg($regexpr,$file)) {
209         require_once($dir.'/'.$file);
210       }
211     }
212   }
213   else {
214     die(_('Folder not found').' : '.$dir);
215   }
216   return true;
217 }
218
219
220 function valid($obj) {
221   LSdebug('function valid() : ok');
222   return true;
223 }
224
225 function validPas($obj=null) {
226   LSdebug('function valid() : nok');
227   return false;
228 }
229
230 function return_data($data) {
231   return $data;
232 }
233
234 function varDump($data) {
235   ob_start();
236   var_dump($data);
237   $data=ob_get_contents(); 
238   ob_end_clean();
239   return $data;
240 }
241
242 $GLOBALS['LSdebug_fields']=array();
243 function LSdebug($data,$dump=false) {
244   if ($dump) {
245     $data=varDump($data);
246   }
247   else if (!is_array($data) && !is_object($data)) {
248     $data="[$data]";
249   }
250   $GLOBALS['LSdebug_fields'][]=$data;
251   LSlog('[DEBUG] '.$data);
252   return true;
253 }
254
255 function LSdebug_print($return=false,$ul=true) {
256   if (( $GLOBALS['LSdebug_fields'] ) && (LSdebug)) {
257     if ($ul) $txt='<ul>'; else $txt="";
258     foreach($GLOBALS['LSdebug_fields'] as $debug) {
259       if (is_array($debug)||is_object($debug)) {
260         $txt.='<li><pre>'.print_r($debug,true).'</pre></li>';
261       }
262       else {
263         $txt.='<li><pre>'.$debug.'</pre></li>';
264       }
265     }
266     if ($ul) $txt.='</ul>';
267     LStemplate :: assign('LSdebug',$txt);
268     if ($return) {
269       return $txt;
270     }
271   }
272   return;
273 }
274
275 function LSdebugDefined() {
276   if (!LSdebug)
277     return;
278   return (!empty($GLOBALS['LSdebug_fields']));
279 }
280
281   /**
282    * Vérifie la compatibilite des DN
283    *
284    * Vérifie que les DNs sont dans la même branche de l'annuaire.
285    *
286    * @param[in] $dn Un premier DN.
287    * @param[in] $dn Un deuxième DN.
288    *
289    * @author Benjamin Renard <brenard@easter-eggs.com>
290    *
291    * @retval boolean true si les DN sont compatibles, false sinon.
292    */ 
293   function isCompatibleDNs($dn1,$dn2) {
294     $infos1=ldap_explode_dn($dn1,0);
295     if(!$infos1)
296       return;
297     $infos2=ldap_explode_dn($dn2,0);
298     if(!$infos2)
299       return;
300     if($infos2['count']>$infos1['count']) {
301       $tmp=$infos1;
302       $infos1=$infos2;
303       $infos2=$tmp;
304     }
305     $infos1=array_reverse($infos1);
306     $infos2=array_reverse($infos2);
307     
308     for($i=0;$i<$infos1['count'];$i++) {
309       if (!isset($infos2[$i])) continue;
310       if($infos1[$i]==$infos2[$i]) continue;
311       return false;
312     }
313     return true;
314   }
315
316   /**
317    * Fait la somme de DN
318    *
319    * Retourne un DN qui correspond au point de séparation des DN si les DN 
320    * ne sont pas dans la meme dans la meme branche ou le dn le plus long sinon.
321    *
322    * @param[in] $dn Un premier DN.
323    * @param[in] $dn Un deuxième DN.
324    *
325    * @author Benjamin Renard <brenard@easter-eggs.com>
326    *
327    * @retval string Un DN (ou false si les DN ne sont pas valide)
328    */ 
329   function sumDn($dn1,$dn2) {
330     $infos1=ldap_explode_dn($dn1,0);
331     if(!$infos1)
332       return;
333     $infos2=ldap_explode_dn($dn2,0);
334     if(!$infos2)
335       return;
336     if($infos2['count']>$infos1['count']) {
337       $tmp=$infos1;
338       $infos1=$infos2;
339       $infos2=$tmp;
340     }
341     $infos1=array_reverse($infos1);
342     $infos2=array_reverse($infos2);
343     
344     $first=true;
345     $basedn='';
346     for($i=0;$i<$infos1['count'];$i++) {
347       if(($infos1[$i]==$infos2[$i])||(!isset($infos2[$i]))) {
348         if($first) {
349           $basedn=$infos1[$i];
350           $first=false;
351         }
352         else
353           $basedn=$infos1[$i].','.$basedn;
354       }
355       else {
356         return $basedn;
357       }
358     }
359     return $basedn;
360   }
361   
362   function checkEmail($value,$domain=NULL,$checkDns=true) {
363     $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
364
365     if (!preg_match($regex, $value)) {
366       LSdebug('checkEmail : regex fail');
367       return false;
368     }
369
370     $nd = explode('@', $value);
371     $nd=$nd[1];
372     
373     if ($domain) {
374       if(is_array($domain)) {
375         if (!in_array($nd,$domain)) {
376           return false;
377         }
378       }
379       else {
380         if($nd!=$domain) {
381           return false;
382         }
383       }
384     }
385
386     if ($checkDns && function_exists('checkdnsrr')) {
387       if (!(checkdnsrr($nd, 'MX') || checkdnsrr($nd, 'A'))) {
388         LSdebug('checkEmail : DNS fail');
389         return false;
390       }
391     }
392
393     return true;
394   }
395   
396   function generatePassword($chars=NULL,$lenght=NULL) {
397     if (!$lenght) {
398         $lenght=8;
399     }
400     if (is_array($chars)) {
401       $retval='';
402       foreach($chars as $chs) {
403         if (!is_array($chs)) {
404           $chs=array('chars' => $chs);
405         }
406         if (!is_int($chs['nb'])) {
407           $chs['nb']=1;
408         }
409         $retval.=aleaChar($chs['chars'],$chs['nb']);
410       }
411       $add = ($lenght-strlen($retval));
412       if ($add > 0) {
413         $retval .= aleaChar($chars,$add);
414       }
415       return str_shuffle($retval);
416     } else {
417       return aleaChar($chars,$lenght);
418     }
419   }
420   
421   function aleaChar($chars=NULL,$lenght=1) {
422     if (is_array($chars)) {
423       $nchars="";
424       foreach($chars as $chs) {
425         if (is_string($chs)) {
426           $nchars.=$chs;
427         }
428         else if (is_string($chs['chars'])) {
429           $nchars.=$chs['chars'];
430         }
431       }
432       if(is_string($chars) && strlen($chars)>0) {
433         $chars=$nchars;
434       }
435       else {
436         $chars=NULL;
437       }
438     }
439     if (!$chars) {
440       $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';    
441     }
442     $nbChars=strlen($chars);
443     $retval="";
444     if(is_int($lenght)) {
445       for ($i=0;$i<$lenght;$i++) {
446         $retval.=$chars[rand(0,$nbChars-1)];
447       }
448     }
449     return $retval;
450   }
451   
452   function compareDn($a,$b) {
453     if (substr_count($a,',') > substr_count($b,','))
454       return -1;
455     else 
456       return 1;
457   }
458   
459   function LSlog($msg,$dump=false) {
460     if ($GLOBALS['LSlog']['enable']) {
461       global $LSlogFile;
462       if (!$LSlogFile) {
463         $LSlogFile=fopen($GLOBALS['LSlog']['filename'],'a');
464       }
465       if ($dump) {
466         $msg=varDump($msg);
467       }
468       else if (is_array($msg)||is_object($msg)) {
469         $msg = print_r($msg,true);
470       }
471       fwrite($LSlogFile,$_SERVER['REQUEST_URI']." : ".$msg."\n");
472     }
473   }
474   
475   function __($msg) {
476     if (isset($GLOBALS['LSlang'][$msg])) {
477       return $GLOBALS['LSlang'][$msg];
478     }
479     return _($msg);
480   }
481   
482  /**
483   * Supprime les accents d'une chaine
484   * 
485   * @param[in] $string La chaine originale
486   * 
487   * @retval string La chaine sans les accents
488   */
489   function withoutAccents($string){
490     $replaceAccent = Array(
491       "à" => "a",
492       "á" => "a",
493       "â" => "a",
494       "ã" => "a",
495       "ä" => "a",
496       "ç" => "c",
497       "è" => "e",
498       "é" => "e",
499       "ê" => "e",
500       "ë" => "e",
501       "ì" => "i",
502       "í" => "i",
503       "î" => "i",
504       "ï" => "i",
505       "ñ" => "n",
506       "ò" => "o",
507       "ó" => "o",
508       "ô" => "o",
509       "õ" => "o",
510       "ö" => "o",
511       "ù" => "u",
512       "ú" => "u",
513       "û" => "u",
514       "ü" => "u",
515       "ý" => "y",
516       "ÿ" => "y",
517       "À" => "A",
518       "Á" => "A",
519       "Â" => "A",
520       "Ã" => "A",
521       "Ä" => "A",
522       "Ç" => "C",
523       "È" => "E",
524       "É" => "E",
525       "Ê" => "E",
526       "Ë" => "E",
527       "Ì" => "I",
528       "Í" => "I",
529       "Î" => "I",
530       "Ï" => "I",
531       "Ñ" => "N",
532       "Ò" => "O",
533       "Ó" => "O",
534       "Ô" => "O",
535       "Õ" => "O",
536       "Ö" => "O",
537       "Ù" => "U",
538       "Ú" => "U",
539       "Û" => "U",
540       "Ü" => "U",
541       "Ý" => "Y"
542     );
543     return strtr($string, $replaceAccent);
544   }
545
546
547  /**
548   * Supprime les espaces d'une chaine en les remplacant par un motif ou non
549   *
550   * @param[in] $str La chaine originale
551   * @param[in] $to Le motif de remplacement. S'il n'est pas spécifié, les espaces seront simplement supprimés
552   *
553   * @retval string La chaine sans les espaces
554   **/
555   function replaceSpaces($str,$to='') {
556     return strtr($str,array (
557                ' ' => $to,
558                "\t" => $to
559              )
560            );
561   }
562
563  /**
564   * List files in a directory corresponding to a regex
565   *
566   * @param[in] $dir The path of the directory
567   * @param[in] $regex The regex apply on filename
568   * 
569   * @retval array() List of file name
570   **/
571   function listFiles($dir,$regex) {
572     $retval=array();
573     if (is_dir($dir)) {
574       $d = dir($dir);
575       while (false !== ($file = $d->read())) {
576         if (is_file("$dir/$file")) {
577           if (preg_match($regex,$file)) {
578             $retval[]=$file;
579           }
580         }
581       }
582     }
583     return $retval;
584   }
585
586  /**
587   * Return current date in LDAP format
588   *
589   * @param[in] $mixed Anything (to permit using as generated function)
590   *
591   * @retval string The current date in LDAP format (YYYYMMDDHHMMSSZ)
592   **/
593   function now($mixed=Null) {
594     return date ('YmdHis').'Z';
595   }
596
597 ?>