<?php
/*******************************************************************************
 * Copyright (C) 2007 Easter-eggs
 * http://ldapsaisie.labs.libre-entreprise.org
 *
 * Author: See AUTHORS file in top-level directory.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

******************************************************************************/

/**
 * Construction d'une chaine formatée
 *
 * Cette fonction retourne la valeur d'une chaine formatée selon le format
 * et les données passés en paramètre.
 *
 * @author Benjamin Renard <brenard@easter-eggs.com>
 *
 * @param[in] $format string Format de la chaine
 * @param[in] $data mixed Les données pour composés la chaine
 *                    Ce paramètre peut être un tableau de string, une string,
 *                    une tableau d'objet ou un objet.
 * @param[in] $meth string Le nom de la methode de/des objet(s) à appeler pour
 *                         obtenir la valeur de remplacement dans la chaine formatée.
 * 
 * @retval string La chaine formatée
 */
function getFData($format,$data,$meth=NULL) {
  $unique=false;
  /*
   * Format : %{[key name][:A][:B][! ou _][~]}
   *
   * Extracted fields
   * - 1 : key name
   * - 2 : :A
   * - 3 : A
   * - 4 : :B
   * - 5 : B
   * - 6 : "-"
   * - 7 : ! or _
   * - 8 : ~
   */
  $expr="/%[{(]([A-Za-z0-9]+)(\:(-?[0-9])+)?(\:(-?[0-9]+))?(-)?(\!|\_)?(~)?[})]/";
  if(!is_array($format)) {
    $format=array($format);
    $unique=true;
  }
  for($i=0;$i<count($format);$i++) {
    if(is_array($data)) {
      if ($meth==NULL) {
        while (preg_match($expr,$format[$i],$ch)) {
          if (is_array($data[$ch[1]])) {
            $val = $data[$ch[1]][0];
          }
          else {
            $val = $data[$ch[1]];
          }
	  $val=_getFData_extractAndModify($val,$ch);
          $format[$i]=str_replace($ch[0],$val,$format[$i]);
        }
      }
      else {
        while (preg_match($expr,$format[$i],$ch)) {
          if (method_exists($data[$ch[1]],$meth)) {
            $value = $data[$ch[1]] -> $meth();
            if (is_array($value)) {
              $value = $value[0];
            }
	    $value=_getFData_extractAndModify($value,$ch);
            $format[$i]=str_replace($ch[0],$value,$format[$i]);
          }
          else {
            LSerror :: addErrorCode('fct_getFData_01',array('meth' => $meth,'obj' => $ch[1]));
            break;
          }
        }
      }
    }
    elseif (is_object($data)) {
      if ($meth==NULL) {
        while (preg_match($expr,$format[$i],$ch)) {
          $value = $data -> $ch[1];
          if (is_array($value)) {
            $value = $value[0];
          }
	  $value=_getFData_extractAndModify($value,$ch);
          $format[$i]=str_replace($ch[0],$value,$format[$i]);
        }
      }
      else {
        while (preg_match($expr,$format[$i],$ch)) {
          if (method_exists($data,$meth)) {
            $value = $data -> $meth($ch[1]);
            if (is_array($value)) {
              $value = $value[0];
            }
	    $value=_getFData_extractAndModify($value,$ch);
            $format[$i]=str_replace($ch[0],$value,$format[$i]);
          }
          else {
            LSerror :: addErrorCode(0,getFData(_("Function 'getFData' : The method %{meth} of the object %{obj} doesn't exist."),array('meth' => $meth,'obj' => get_class($data))));
            break;
          }
        }
      }
    }
    else {
      while (preg_match($expr,$format[$i],$ch)) {
	$val=_getFData_extractAndModify($data,$ch);
        $format[$i]=str_replace($ch[0],$val,$format[$i]);
      }
    }
  }
  if($unique) {
    return $format[0];
  }
  return $format;
}

function _getFData_extractAndModify($data,$ch) {
  if($ch[3]) {
    if ($ch[5]) {
      if ($ch[6]) {
	if ($ch[3]<0) {
          $s=strlen((string)$data)-(-1*$ch[3])-$ch[5];
          $l=$ch[5];
        }
        else {
          $s=$ch[3]-$ch[5];
          $l=$ch[5];
          if ($s<0) {
            $l=$l-(-1*$s);
	    $s=0;
          }
        }
      }
      else {
        $s=$ch[3];
        $l=$ch[5];
      }
    }
    else if ($ch[5]==0) {
      if ($ch[3]<0) {
        $s=strlen((string)$data)-(-1*$ch[3]);
        $l=strlen((string)$data);
      }
      else {
        $s=$ch[3];
	$l=strlen((string)$data);
      }
    }
    else {
      $s=0;
      $l=$ch[3];
    }
    $val=substr((string)$data,$s,$l);
  }
  else {
    try {
      $val=strval($data);
    }
    catch (Exception $e) {
      $val=_('[not string value]');
    }
  }

  # Without Accent
  if ($ch[8]) {
    $val = withoutAccents($val);
  }
 
  # Upper / Lower case
  if ($ch[7]=="!") {
    $val=strtoupper($val);
  }
  elseif ($ch[7]=='_') {
    $val=strtolower($val);
  }

  return $val;
}

function getFieldInFormat($format) {
  $fields=array();
  $expr='/%[{(]([A-Za-z0-9]+)(\:(-?[0-9])+)?(\:(-?[0-9]+))?(-)?(\!|\_)?(~)?[})]/';
  while (preg_match($expr,$format,$ch)) {
    $fields[]=$ch[1];
    $format=str_replace($ch[0],'',$format);
  }
  return $fields;
}

function loadDir($dir,$regexpr='/^.*\.php$/') {
  if ($handle = opendir($dir)) {
    while (false !== ($file = readdir($handle))) {
      if (preg_match($regexpr,$file)) {
        require_once($dir.'/'.$file);
      }
    }
  }
  else {
    die(_('Folder not found').' : '.$dir);
  }
  return true;
}


function valid($obj) {
  LSdebug('function valid() : ok');
  return true;
}

function validPas($obj=null) {
  LSdebug('function valid() : nok');
  return false;
}

function return_data($data) {
  return $data;
}

function varDump($data) {
  ob_start();
  var_dump($data);
  $data=ob_get_contents(); 
  ob_end_clean();
  return $data;
}

$GLOBALS['LSdebug_fields']=array();
function LSdebug($data,$dump=false) {
  if ($dump) {
    $data=varDump($data);
  }
  else if (!is_array($data) && !is_object($data)) {
    $data="[$data]";
  }
  $GLOBALS['LSdebug_fields'][]=$data;
  LSlog('[DEBUG] '.$data);
  return true;
}

function LSdebug_print($return=false,$ul=true) {
  if (( $GLOBALS['LSdebug_fields'] ) && (LSdebug)) {
    if ($ul) $txt='<ul>'; else $txt="";
    foreach($GLOBALS['LSdebug_fields'] as $debug) {
      if (is_array($debug)||is_object($debug)) {
        $txt.='<li><pre>'.print_r($debug,true).'</pre></li>';
      }
      else {
        $txt.='<li><pre>'.$debug.'</pre></li>';
      }
    }
    if ($ul) $txt.='</ul>';
    LStemplate :: assign('LSdebug',$txt);
    if ($return) {
      return $txt;
    }
  }
  return;
}

function LSdebugDefined() {
  if (!LSdebug)
    return;
  return (!empty($GLOBALS['LSdebug_fields']));
}

  /**
   * Vérifie la compatibilite des DN
   *
   * Vérifie que les DNs sont dans la même branche de l'annuaire.
   *
   * @param[in] $dn Un premier DN.
   * @param[in] $dn Un deuxième DN.
   *
   * @author Benjamin Renard <brenard@easter-eggs.com>
   *
   * @retval boolean true si les DN sont compatibles, false sinon.
   */ 
  function isCompatibleDNs($dn1,$dn2) {
    $infos1=ldap_explode_dn($dn1,0);
    if(!$infos1)
      return;
    $infos2=ldap_explode_dn($dn2,0);
    if(!$infos2)
      return;
    if($infos2['count']>$infos1['count']) {
      $tmp=$infos1;
      $infos1=$infos2;
      $infos2=$tmp;
    }
    $infos1=array_reverse($infos1);
    $infos2=array_reverse($infos2);
    
    for($i=0;$i<$infos1['count'];$i++) {
      if (!isset($infos2[$i])) continue;
      if($infos1[$i]==$infos2[$i]) continue;
      return false;
    }
    return true;
  }

  /**
   * Fait la somme de DN
   *
   * Retourne un DN qui correspond au point de séparation des DN si les DN 
   * ne sont pas dans la meme dans la meme branche ou le dn le plus long sinon.
   *
   * @param[in] $dn Un premier DN.
   * @param[in] $dn Un deuxième DN.
   *
   * @author Benjamin Renard <brenard@easter-eggs.com>
   *
   * @retval string Un DN (ou false si les DN ne sont pas valide)
   */ 
  function sumDn($dn1,$dn2) {
    $infos1=ldap_explode_dn($dn1,0);
    if(!$infos1)
      return;
    $infos2=ldap_explode_dn($dn2,0);
    if(!$infos2)
      return;
    if($infos2['count']>$infos1['count']) {
      $tmp=$infos1;
      $infos1=$infos2;
      $infos2=$tmp;
    }
    $infos1=array_reverse($infos1);
    $infos2=array_reverse($infos2);
    
    $first=true;
    $basedn='';
    for($i=0;$i<$infos1['count'];$i++) {
      if(($infos1[$i]==$infos2[$i])||(!isset($infos2[$i]))) {
        if($first) {
          $basedn=$infos1[$i];
          $first=false;
        }
        else
          $basedn=$infos1[$i].','.$basedn;
      }
      else {
        return $basedn;
      }
    }
    return $basedn;
  }
  
  function checkEmail($value,$domain=NULL,$checkDns=true) {
    $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\-]+))$/';

    if (!preg_match($regex, $value)) {
      LSdebug('checkEmail : regex fail');
      return false;
    }

    $nd = explode('@', $value);
    $nd=$nd[1];
    
    if ($domain) {
      if(is_array($domain)) {
        if (!in_array($nd,$domain)) {
          return false;
        }
      }
      else {
        if($nd!=$domain) {
          return false;
        }
      }
    }

    if ($checkDns && function_exists('checkdnsrr')) {
      if (!(checkdnsrr($nd, 'MX') || checkdnsrr($nd, 'A'))) {
        LSdebug('checkEmail : DNS fail');
        return false;
      }
    }

    return true;
  }
  
  function generatePassword($chars=NULL,$lenght=NULL) {
    if (!$lenght) {
        $lenght=8;
    }
    if (is_array($chars)) {
      $retval='';
      foreach($chars as $chs) {
        if (!is_array($chs)) {
          $chs=array('chars' => $chs);
        }
        if (!is_int($chs['nb'])) {
          $chs['nb']=1;
        }
        $retval.=aleaChar($chs['chars'],$chs['nb']);
      }
      $add = ($lenght-strlen($retval));
      if ($add > 0) {
        $retval .= aleaChar($chars,$add);
      }
      return str_shuffle($retval);
    } else {
      return aleaChar($chars,$lenght);
    }
  }
  
  function aleaChar($chars=NULL,$lenght=1) {
    if (is_array($chars)) {
      $nchars="";
      foreach($chars as $chs) {
        if (is_string($chs)) {
          $nchars.=$chs;
        }
        else if (is_string($chs['chars'])) {
          $nchars.=$chs['chars'];
        }
      }
      if(is_string($chars) && strlen($chars)>0) {
        $chars=$nchars;
      }
      else {
        $chars=NULL;
      }
    }
    if (!$chars) {
      $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';    
    }
    $nbChars=strlen($chars);
    $retval="";
    if(is_int($lenght)) {
      for ($i=0;$i<$lenght;$i++) {
        $retval.=$chars[rand(0,$nbChars-1)];
      }
    }
    return $retval;
  }
  
  function compareDn($a,$b) {
    if (substr_count($a,',') > substr_count($b,','))
      return -1;
    else 
      return 1;
  }
  
  function LSlog($msg,$dump=false) {
    if ($GLOBALS['LSlog']['enable']) {
      global $LSlogFile;
      if (!$LSlogFile) {
        $LSlogFile=fopen($GLOBALS['LSlog']['filename'],'a');
      }
      if ($dump) {
        $msg=varDump($msg);
      }
      else if (is_array($msg)||is_object($msg)) {
        $msg = print_r($msg,true);
      }
      fwrite($LSlogFile,$_SERVER['REQUEST_URI']." : ".$msg."\n");
    }
  }
  
  function __($msg) {
    if (isset($GLOBALS['LSlang'][$msg])) {
      return $GLOBALS['LSlang'][$msg];
    }
    return _($msg);
  }
  
 /**
  * Supprime les accents d'une chaine
  * 
  * @param[in] $string La chaine originale
  * 
  * @retval string La chaine sans les accents
  */
  function withoutAccents($string){
    $replaceAccent = Array(
      "à" => "a",
      "á" => "a",
      "â" => "a",
      "ã" => "a",
      "ä" => "a",
      "ç" => "c",
      "è" => "e",
      "é" => "e",
      "ê" => "e",
      "ë" => "e",
      "ì" => "i",
      "í" => "i",
      "î" => "i",
      "ï" => "i",
      "ñ" => "n",
      "ò" => "o",
      "ó" => "o",
      "ô" => "o",
      "õ" => "o",
      "ö" => "o",
      "ù" => "u",
      "ú" => "u",
      "û" => "u",
      "ü" => "u",
      "ý" => "y",
      "ÿ" => "y",
      "À" => "A",
      "Á" => "A",
      "Â" => "A",
      "Ã" => "A",
      "Ä" => "A",
      "Ç" => "C",
      "È" => "E",
      "É" => "E",
      "Ê" => "E",
      "Ë" => "E",
      "Ì" => "I",
      "Í" => "I",
      "Î" => "I",
      "Ï" => "I",
      "Ñ" => "N",
      "Ò" => "O",
      "Ó" => "O",
      "Ô" => "O",
      "Õ" => "O",
      "Ö" => "O",
      "Ù" => "U",
      "Ú" => "U",
      "Û" => "U",
      "Ü" => "U",
      "Ý" => "Y"
    );
    return strtr($string, $replaceAccent);
  }


 /**
  * Supprime les espaces d'une chaine en les remplacant par un motif ou non
  *
  * @param[in] $str La chaine originale
  * @param[in] $to Le motif de remplacement. S'il n'est pas spécifié, les espaces seront simplement supprimés
  *
  * @retval string La chaine sans les espaces
  **/
  function replaceSpaces($str,$to='') {
    return strtr($str,array (
               ' ' => $to,
               "\t" => $to
             )
           );
  }

 /**
  * List files in a directory corresponding to a regex
  *
  * @param[in] $dir The path of the directory
  * @param[in] $regex The regex apply on filename
  * 
  * @retval array() List of file name
  **/
  function listFiles($dir,$regex) {
    $retval=array();
    if (is_dir($dir)) {
      $d = dir($dir);
      while (false !== ($file = $d->read())) {
        if (is_file("$dir/$file")) {
          if (preg_match($regex,$file)) {
            $retval[]=$file;
          }
        }
      }
    }
    return $retval;
  }

 /**
  * Return current date in LDAP format
  *
  * @param[in] $mixed Anything (to permit using as generated function)
  *
  * @retval string The current date in LDAP format (YYYYMMDDHHMMSSZ)
  **/
  function now($mixed=Null) {
    return date ('YmdHis').'Z';
  }

?>