From: cajus Date: Thu, 12 May 2005 06:45:38 +0000 (+0000) Subject: Completed migration X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=c2c6a6e54355a1b67c25bb4d761d847513810d02;p=gosa.git Completed migration git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@188 594d385d-05f5-0310-b6e9-bd551577e9d8 --- diff --git a/include/class_config.inc b/include/class_config.inc new file mode 100644 index 000000000..bbab2e276 --- /dev/null +++ b/include/class_config.inc @@ -0,0 +1,448 @@ + array(), 'LOCATIONS' => array(), 'SERVERS' => array(), + 'MAIN' => array( 'LANGUAGES' => array(), 'FAXFORMATS' => array() ), + 'MENU' => array(), 'SERVICE' => array()); + var $basedir= ""; + + /* Keep a copy of the current deparment list */ + var $departments= array(); + var $idepartments= array(); + + function config($filename, $basedir= "") + { + $this->parser = xml_parser_create(); + $this->basedir= $basedir; + + xml_set_object($this->parser, $this); + xml_set_element_handler($this->parser, "tag_open", "tag_close"); + + /* Parse config file directly? */ + if ($filename != ""){ + $this->parse($filename); + } + } + + function parse($filename) + { + $fh= fopen($filename, "r"); + $xmldata= fread($fh, 100000); + fclose($fh); + if(!xml_parse($this->parser, chop($xmldata))){ + print_red(sprintf(_("XML error in gosa.conf: %s at line %d"), + xml_error_string(xml_get_error_code($this->parser)), + xml_get_current_line_number($this->parser))); + echo $_SESSION['errors']; + exit; + } + } + + function tag_open($parser, $tag, $attrs) + { + /* Save last and current tag for reference */ + $this->tags[$this->level]= $tag; + $this->level++; + + /* Trigger on CONF section */ + if ($tag == 'CONF'){ + $this->config_found= TRUE; + } + + /* Return if we're not in config section */ + if (!$this->config_found){ + return; + } + + /* Look through attributes */ + switch ($this->tags[$this->level-1]){ + + /* Handle tab section */ + case 'TAB': $name= $this->tags[$this->level-2]; + + /* Create new array? */ + if (!isset($this->data['TABS'][$name])){ + $this->data['TABS'][$name]= array(); + } + + /* Add elements */ + $this->data['TABS'][$name][]= $attrs; + break; + + /* Handle location */ + case 'LOCATION': + if ($this->tags[$this->level-2] == 'MAIN'){ + $name= $attrs['NAME']; + $this->currentLocation= $name; + + /* Add location elements */ + $this->data['LOCATIONS'][$name]= $attrs; + } + break; + + /* Handle referral tags */ + case 'REFERRAL': + if ($this->tags[$this->level-2] == 'LOCATION'){ + $url= $attrs['URL']; + $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url); + + /* Add location elements */ + if (!isset($this->data['LOCATIONS'][$this->currentLocation]['REFERRAL'])){ + $this->data['LOCATIONS'][$this->currentLocation]['REFERRAL']= array(); + } + + $this->data['LOCATIONS'][$this->currentLocation]['REFERRAL'][$server]= $attrs; + } + break; + + /* Handle language */ + case 'LANGUAGE': + if ($this->tags[$this->level-2] == 'MAIN'){ + /* Add languages */ + $this->data['MAIN']['LANGUAGES'][$attrs['NAME']]= + $attrs['TAG']; + } + break; + + /* Handle faxformat */ + case 'FAXFORMAT': + if ($this->tags[$this->level-2] == 'MAIN'){ + /* Add fax formats */ + $this->data['MAIN']['FAXFORMATS'][]= $attrs['TYPE']; + } + break; + + /* Load main parameters */ + case 'MAIN': + $this->data['MAIN']= array_merge ($this->data['MAIN'], $attrs); + break; + + /* Load menu */ + case 'SECTION': + if ($this->tags[$this->level-2] == 'MENU'){ + $this->section= $attrs['NAME']; + $this->data['MENU'][$this->section]= array(); ; + } + break; + + /* Inser plugins */ + case 'PLUGIN': + if ($this->tags[$this->level-3] == 'MENU' && + $this->tags[$this->level-2] == 'SECTION'){ + + $this->data['MENU'][$this->section][$this->gpc++]= $attrs; + } + if ($this->tags[$this->level-2] == 'SERVICEMENU'){ + $this->data['SERVICE'][$attrs['CLASS']]= $attrs; + } + break; + } + } + + function tag_close($parser, $tag) + { + /* Close config section */ + if ($tag == 'CONF'){ + $this->config_found= FALSE; + } + $this->level--; + } + + function get_ldap_link($sizelimit= FALSE) + { + /* Build new connection */ + $this->ldap= ldap_init ($this->current['SERVER'], $this->current['BASE'], + $this->current['ADMIN'], $this->current['PASSWORD']); + + /* Check for connection */ + if (is_null($this->ldap) || (is_int($this->ldap) && $this->ldap == 0)){ + print_red (_("Can't bind to LDAP. Please contact the system administrator.")); + echo $_SESSION['errors']; + exit; + } + + if (!isset($_SESSION['size_limit'])){ + $_SESSION['size_limit']= $this->current['SIZELIMIT']; + $_SESSION['size_ignore']= $this->current['SIZEIGNORE']; + } + + if ($sizelimit){ + $this->ldap->set_size_limit($_SESSION['size_limit']); + } else { + $this->ldap->set_size_limit(0); + } + + /* Move referrals */ + if (!isset($this->current['REFERRAL'])){ + $this->ldap->referrals= array(); + } else { + $this->ldap->referrals= $this->current['REFERRAL']; + } + + return ($this->ldap); + } + + function set_current($name) + { + $this->current= $this->data['LOCATIONS'][$name]; + if (!isset($this->current['PEOPLE'])){ + $this->current['PEOPLE']= "ou=people"; + } + if (!isset($this->current['GROUPS'])){ + $this->current['GROUPS']= "ou=groups"; + } + if (!isset($this->current['WINSTATIONS'])){ + $this->current['WINSTATIONS']= "ou=winstations,ou=systems"; + } + if (!isset($this->current['HASH'])){ + $this->current['HASH']= "crypt"; + } + if (!isset($this->current['DNMODE'])){ + $this->current['DNMODE']= "cn"; + } + if (!isset($this->current['MINID'])){ + $this->current['MINID']= 100; + } + if (!isset($this->current['SIZELIMIT'])){ + $this->current['SIZELIMIT']= 200; + } + if (!isset($this->current['SIZEINGORE'])){ + $this->current['SIZEIGNORE']= TRUE; + } else { + if (preg_match("/true/i", $this->current['SIZEIGNORE'])){ + $this->current['SIZEIGNORE']= TRUE; + } else { + $this->current['SIZEIGNORE']= FALSE; + } + } + + /* Sort referrals, if present */ + if (isset ($this->current['REFERRAL'])){ + $bases= array(); + $servers= array(); + foreach ($this->current['REFERRAL'] as $ref){ + $server= preg_replace('%^(.*)/[^/]+$%', '\\1', $ref['URL']); + $base= preg_replace('%^.*/([^/]+)$%', '\\1', $ref['URL']); + $bases[$base]= strlen($base); + $servers[$base]= $server; + } + asort($bases); + reset($bases); + } + + /* SERVER not defined? Load the one with the shortest base */ + if (!isset($this->current['SERVER'])){ + $this->current['SERVER']= $servers[key($bases)]; + } + + /* BASE not defined? Load the one with the shortest base */ + if (!isset($this->current['BASE'])){ + $this->current['BASE']= key($bases); + } + + /* Parse LDAP referral informations */ + if (!isset($this->current['ADMIN']) || !isset($this->current['PASSWORD'])){ + $url= $this->current['SERVER']; + $referral= $this->current['REFERRAL'][$url]; + $this->current['ADMIN']= $referral['ADMIN']; + $this->current['PASSWORD']= $referral['PASSWORD']; + } + + /* Load server informations */ + $this->load_servers(); + } + + function load_servers () + { + /* Only perform actions if current is set */ + if ($this->current == NULL){ + return; + } + + /* Fill imap servers */ + $ldap= $this->get_ldap_link(); + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goImapServer)"); + + $this->data['SERVERS']['IMAP']= array(); + error_reporting(0); + while ($attrs= $ldap->fetch()){ + $name= $attrs['goImapName'][0]; + $this->data['SERVERS']['IMAP'][$name]= array( "connect" => $attrs['goImapConnect'][0], + "admin" => $attrs['goImapAdmin'][0], + "password" => $attrs['goImapPassword'][0], + "sieve_server" => $attrs['goImapSieveServer'][0], + "sieve_port" => $attrs['goImapSievePort'][0]); + } + error_reporting(E_ALL); + + /* Get kerberos server. FIXME: only one is supported currently */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goKrbServer)"); + if ($ldap->count()){ + $attrs= $ldap->fetch(); + $this->data['SERVERS']['KERBEROS']= array( 'SERVER' => $attrs['cn'][0], + 'REALM' => $attrs['goKrbRealm'][0], + 'ADMIN' => $attrs['goKrbAdmin'][0], + 'PASSWORD' => $attrs['goKrbPassword'][0]); + } + + /* Get cups server. FIXME: only one is supported currently */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goCupsServer)"); + if ($ldap->count()){ + $attrs= $ldap->fetch(); + $this->data['SERVERS']['CUPS']= $attrs['cn'][0]; + } + + /* Get fax server. FIXME: only one is supported currently */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goFaxServer)"); + if ($ldap->count()){ + $attrs= $ldap->fetch(); + $this->data['SERVERS']['FAX']= array( 'SERVER' => $attrs['cn'][0], + 'LOGIN' => $attrs['goFaxAdmin'][0], + 'PASSWORD' => $attrs['goFaxPassword'][0]); + } + + /* Get asterisk servers */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goFonServer)"); + if ($ldap->count()){ + $attrs= $ldap->fetch(); + $this->data['SERVERS']['FON']= array( 'SERVER' => $attrs['cn'][0], + 'LOGIN' => $attrs['goFonAdmin'][0], + 'PASSWORD' => $attrs['goFonPassword'][0]); + } + /* Get logdb server */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goLogDBServer)"); + if ($ldap->count()){ + $attrs= $ldap->fetch(); + $this->data['SERVERS']['LOG']= array( 'SERVER' => $attrs['cn'][0], + 'LOGIN' => $attrs['goLogAdmin'][0], + 'PASSWORD' => $attrs['goLogPassword'][0]); + } + + /* Get NFS server lists */ + $tmp= array("default"); + $ldap->cd ($this->current['BASE']); + $ldap->search ("(&(objectClass=goNfsServer)(goExportEntry=*))"); + while ($attrs= $ldap->fetch()){ + for ($i= 0; $i<$attrs["goExportEntry"]["count"]; $i++){ + $path= preg_replace ("/\s.*$/", "", $attrs["goExportEntry"][$i]); + $tmp[]= $attrs["cn"][0].":$path"; + } + } + $this->data['SERVERS']['NFS']= $tmp; + + + /* Load Terminalservers */ + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goTerminalServer)"); + $this->data['SERVERS']['TERMINAL'][]= "default"; + $this->data['SERVERS']['FONT'][]= "default"; + while ($attrs= $ldap->fetch()){ + $this->data['SERVERS']['TERMINAL'][]= $attrs["cn"][0]; + for ($i= 0; $i<$attrs["goFontPath"]["count"]; $i++){ + $this->data['SERVERS']['FONT'][]= $attrs["goFontPath"][$i]; + } + } + + /* Ldap Server */ + $this->data['SERVERS']['LDAP']= array("default"); + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goLdapServer)"); + while ($attrs= $ldap->fetch()){ + for ($i= 0; $i<$attrs["goLdapBase"]["count"]; $i++){ + $this->data['SERVERS']['LDAP'][]= $attrs["cn"][0].":".$attrs["goLdapBase"][$i]; + } + } + + /* Get misc server lists */ + $this->data['SERVERS']['SYSLOG']= array("default"); + $this->data['SERVERS']['NTP']= array("default"); + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goNtpServer)"); + while ($attrs= $ldap->fetch()){ + $this->data['SERVERS']['NTP'][]= $attrs["cn"][0]; + } + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=goSyslogServer)"); + while ($attrs= $ldap->fetch()){ + $this->data['SERVERS']['SYSLOG'][]= $attrs["cn"][0]; + } + + /* Get samba servers from LDAP, in case of samba3 */ + if ($this->current['SAMBAVERSION'] == 3){ + $this->data['SERVERS']['SAMBA']= array(); + $ldap->cd ($this->current['BASE']); + $ldap->search ("(objectClass=sambaDomain)"); + while ($attrs= $ldap->fetch()){ + $this->data['SERVERS']['SAMBA'][$attrs['sambaDomainName'][0]]= array( + "SID" => $attrs["sambaSID"][0], + "RIDBASE" => $attrs["sambaAlgorithmicRidBase"][0]); + } + + /* If no samba servers are found, look for configured sid/ridbase */ + if (count($this->data['SERVERS']['SAMBA']) == 0){ + if (!isset($this->current["SID"]) || !isset($this->current["RIDBASE"])){ + print_red(_("SID and/or RIDBASE missing in your configuration!")); + echo $_SESSION['errors']; + exit; + } else { + $this->data['SERVERS']['SAMBA']['DEFAULT']= array( + "SID" => $this->current["SID"], + "RIDBASE" => $this->current["RIDBASE"]); + } + } + } + } + + function make_idepartments() + { + $this->idepartments= array(); + foreach ($this->departments as $key => $val){ + $this->idepartments[$val]= $key; + } + } + +} + +?> diff --git a/include/class_ldap.inc b/include/class_ldap.inc new file mode 100644 index 000000000..f3650a55e --- /dev/null +++ b/include/class_ldap.inc @@ -0,0 +1,775 @@ + + Copyright (C) 2004 Cajus Pollmeier + + Based in code of ldap.inc of + Copyright (C) 1998 Eric Kilfoil + *****************************************************************************/ + +define("ALREADY_EXISTING_ENTRY",-10001); +define("UNKNOWN_TOKEN_IN_LDIF_FILE",-10002); +define("NO_FILE_UPLOADED",10003); + + +define("INSERT_OK",10000); + + + +class LDAP{ + + var $hascon =false; + var $hasres =false; + var $reconnect=false; + var $tls = false; + var $basedn =""; + var $cid; + var $error = ""; // Any error messages to be returned can be put here + var $start = 0; // 0 if we are fetching the first entry, otherwise 1 + var $objectClasses = array(); // Information read from slapd.oc.conf + var $binddn = ""; + var $bindpw = ""; + var $hostname = ""; + var $follow_referral = FALSE; + var $referrals= array(); + + function LDAP($binddn,$bindpw, $hostname, $follow_referral= FALSE, $tls= FALSE) + { + $this->follow_referral= $follow_referral; + $this->tls=$tls; + $this->binddn=$binddn; + $this->bindpw=$bindpw; + $this->hostname=$hostname; + $this->connect(); + } + + function connect() + { + $this->hascon=false; + $this->reconnect=false; + if ($this->cid= @ldap_connect($this->hostname)) { + @ldap_set_option($this->cid, LDAP_OPT_PROTOCOL_VERSION, 3); + if (function_exists("ldap_set_rebind_proc") && $this->follow_referral) { + @ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1); + @ldap_set_rebind_proc($this->cid, array(&$this, "rebind")); + } + if (function_exists("ldap_start_tls") && $this->tls){ + @ldap_start_tls($this->cid); + } + + $this->error = "No Error"; + if ($bid = @ldap_bind($this->cid, $this->binddn, $this->bindpw)) { + $this->error = "Success"; + $this->hascon=true; + } else { + if ($this->reconnect){ + if ($this->error != "Success"){ + $this->error = "Could not rebind to " . $this->binddn; + } + } else { + $this->error = "Could not bind to " . $this->binddn; + } + } + } else { + $this->error = "Could not connect to LDAP server"; + } + } + + function rebind($ldap, $referral) + { + $credentials= $this->get_credentials($referral); + if (@ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) { + $this->error = "Success"; + $this->hascon=true; + $this->reconnect= true; + return (0); + } else { + $this->error = "Could not bind to " . $binddn; + return NULL; + } + } + + function reconnect() + { + if ($this->reconnect){ + @ldap_unbind($this->cid); + $this->cid = NULL; + } + } + + function unbind() + { + @ldap_unbind($this->cid); + $this->cid = NULL; + } + + function disconnect() + { + if($this->hascon){ + @ldap_close($this->cid); + $this->hascon=false; + } + } + + function cd($dir) + { + if ($dir == "..") + $this->basedn = $this->getParentDir(); + else + $this->basedn = $dir; + } + + function getParentDir($basedn = "") + { + if ($basedn=="") + $basedn = $this->basedn; + return(ereg_replace("[^,]*[,]*[ ]*(.*)", "\\1", $basedn)); + } + + function search($filter, $attrs= array()) + { + + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $this->clearResult(); + $this->sr = @ldap_search($this->cid, $this->basedn, $filter, $attrs); + $this->error = @ldap_error($this->cid); + $this->resetResult(); + $this->hasres=true; + return($this->sr); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function ls($filter = "(objectclass=*)", $basedn = "") + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $this->clearResult(); + if ($basedn == "") + $basedn = $this->basedn; + $this->sr = @ldap_list($this->cid, $basedn, $filter); + $ldap->error = @ldap_error($this->cid); + $this->resetResult(); + $this->hasres=true; + return($this->sr); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function cat($dn) + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $this->clearResult(); + $filter = "(objectclass=*)"; + $this->sr = @ldap_read($this->cid, $dn, $filter); + $this->error = @ldap_error($this->cid); + $this->resetResult(); + $this->hasres=true; + return($this->sr); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function set_size_limit($size) + { + /* Ignore zero settings */ + if ($size == 0){ + @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000); + } + if($this->hascon){ + @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size); + } else { + $this->error = "Could not connect to LDAP server"; + } + } + + function fetch() + { + if($this->hascon){ + if($this->hasres){ + if ($this->start == 0) + { + $this->start = 1; + $this->re= @ldap_first_entry($this->cid, $this->sr); + } else { + $this->re= @ldap_next_entry($this->cid, $this->re); + } + if ($this->re) + { + $att= @ldap_get_attributes($this->cid, $this->re); + $att['dn']= @ldap_get_dn($this->cid, $this->re); + } + $ldap->error = @ldap_error($this->cid); + if (!isset($att)){ + $att= array(); + } + return($att); + }else{ + $this->error = "Perform a Fetch with no Search"; + return(""); + } + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function resetResult() + { + $this->start = 0; + } + + function clearResult() + { + if($this->hasres){ + $this->hasres = false; + @ldap_free_result($this->sr); + } + } + + function getDN() + { + if($this->hascon){ + if($this->hasres){ + + if(!$this->re) + { + $this->error = "Perform a Fetch with no valid Result"; + } + else + { + $rv = @ldap_get_dn($this->cid, $this->re); + + $ldap->error = @ldap_error($this->cid); + $rv= preg_replace("/[ ]*,[ ]*/", ",", $rv); + return($rv); + } + }else{ + $this->error = "Perform a Fetch with no Search"; + return(""); + } + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function count() + { + if($this->hascon){ + if($this->hasres){ + $rv = @ldap_count_entries($this->cid, $this->sr); + $ldap->error = @ldap_error($this->cid); + return($rv); + }else{ + $this->error = "Perform a Fetch with no Search"; + return(""); + } + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function rm($attrs = "", $dn = "") + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + if ($dn == "") + $dn = $this->basedn; + + $r = @ldap_mod_del($this->cid, $dn, $attrs); + $ldap->error = @ldap_error($this->cid); + return($r); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function rename($attrs, $dn = "") + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + if ($dn == "") + $dn = $this->basedn; + + $r = @ldap_mod_replace($this->cid, $dn, $attrs); + $ldap->error = @ldap_error($this->cid); + return($r); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function rmdir($deletedn) + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $r = @ldap_delete($this->cid, $deletedn); + $this->error = @ldap_error($this->cid); + return($r ? $r : 0); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function modify($attrs) + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $r = @ldap_modify($this->cid, $this->basedn, $attrs); + $this->error = @ldap_error($this->cid); + return($r ? $r : 0); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function add($attrs) + { + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $r = @ldap_add($this->cid, $this->basedn, $attrs); + $this->error = @ldap_error($this->cid); + return($r ? $r : 0); + }else{ + $this->error = "Could not connect to LDAP server"; + return(""); + } + } + + function create_missing_trees($target) + { + + /* Ignore create_missing trees if the base equals target */ + if ($target == $this->basedn){ + return; + } + $l= array_reverse(explode(",", preg_replace("/,".$this->basedn."/", "", $target))); + $cdn= $this->basedn; + foreach ($l as $part){ + $cdn= "$part,$cdn"; + + /* Ignore referrals */ + $found= false; + foreach($this->referrals as $ref){ + $base= preg_replace('!^[^:]+://[^/]+/([^?]+).*$!', '\\1', $ref['URL']); + if ($base == $cdn){ + $found= true; + break; + } + } + if ($found){ + continue; + } + + $this->cat ($cdn); + $attrs= $this->fetch(); + + /* Create missing entry? */ + if (!count ($attrs)){ + $type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn); + $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn); + + $na= array(); + switch ($type){ + case 'ou': + $na["objectClass"]= "organizationalUnit"; + $na["ou"]= $param; + break; + case 'dc': + $na["objectClass"]= array("dcObject", "top", "locality"); + $na["dc"]= $param; + break; + default: + print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type)); + exit; + } + $this->cd($cdn); + $this->add($na); + } + } + } + + function recursive_remove() + { + $delarray= array(); + + /* Get sorted list of dn's to delete */ + $this->search ("(objectClass=*)"); + while ($this->fetch()){ + $deldn= $this->getDN(); + $delarray[$deldn]= strlen($deldn); + } + arsort ($delarray); + reset ($delarray); + + /* Delete all dn's in subtree */ + foreach ($delarray as $key => $value){ + $this->rmdir($key); + } + } + + function get_attribute($dn, $name) + { + $data= ""; + if ($this->reconnect) $this->connect(); + $sr= @ldap_read($this->cid, $dn, "objectClass=*", array("$name")); + + /* fill data from LDAP */ + if ($sr) { + $ei= @ldap_first_entry($this->cid, $sr); + if ($ei) { + if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){ + $data= $info[0]; + } + } + } + + return ($data); + } + + function get_additional_error() + { + $error= ""; + @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error); + return ($error); + } + + function get_error() + { + if ($this->error == 'Success'){ + return $this->error; + } else { + $error= $this->error." (".$this->get_additional_error().")"; + return $error; + } + } + + function get_credentials($url, $referrals= NULL) + { + $ret= array(); + $url= preg_replace('!\?\?.*$!', '', $url); + $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url); + + if ($referrals == NULL){ + $referrals= $this->referrals; + } + + if (isset($referrals[$server])){ + return ($referrals[$server]); + } else { + $ret['ADMIN']= $this->binddn; + $ret['PASSWORD']= $this->bindpw; + } + + return ($ret); + } + + + function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE) + { + $display= ""; + + if ($recursive){ + $this->cd($dn); + $this->search("$filter", array('dn')); + while ($attrs= $this->fetch()){ + $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes); + $display.= "\n"; + } + } else { + $display.= $this->gen_one_entry($dn); + } + + return ($display); + } + + + function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*")) + { + $ret = ""; + $data = ""; + if($this->reconnect){ + $this->connect(); + } + + /* Searching Ldap Tree */ + $sr= @ldap_read($this->cid, $dn, $filter, $name); + + /* Get the first entry */ + $entry= @ldap_first_entry($this->cid, $sr); + + /* Get all attributes related to that Objekt */ + $atts = array(); + + /* Assemble dn */ + $atts[0]['name'] = "dn"; + $atts[0]['value'] = array('count' => 1, 0 => $dn); + + /* Reset index */ + $i = 1 ; + + $attribute= @ldap_first_attribute($this->cid,$entry,$identifier); + while ($attribute) { + $i++; + $atts[$i]['name'] = $attribute; + $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute"); + + /* Next one */ + $attribute= @ldap_next_attribute($this->cid,$entry,$identifier); + } + + foreach($atts as $at) + { + for ($i= 0; $i<$at['value']['count']; $i++){ + + /* Check if we must encode the data */ + if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) { + $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n"; + } else { + $ret .= $at['name'].": ".$at['value'][$i]."\n"; + } + } + } + + return($ret); + } + + + function dn_exists($dn) + { + return @ldap_list($this->cid, $dn, "(objectClass=*)", array("objectClass")); + } + + + + function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup) + { + if($this->reconnect) $this->connect(); + + /* First we have to splitt the string ito detect empty lines + An empty line indicates an new Entry */ + $entries = split("\n",$str_attr); + + $data = ""; + $cnt = 0; + $current_line = 0; + + /* Every single line ... */ + foreach($entries as $entry) { + $current_line ++; + + /* Removing Spaces to .. + .. test if a new entry begins */ + $tmp = str_replace(" ","",$data ); + + /* .. prevent empty lines in an entry */ + $tmp2 = str_replace(" ","",$entry); + + /* If the Block ends (Empty Line) */ + if((empty($entry))&&(!empty($tmp))) { + /* Add collected lines as a complete block */ + $all[$cnt] = $data; + $cnt ++; + $data =""; + } else { + + /* Append lines ... */ + if(!empty($tmp2)) { + /* check if we need base64_decode for this line */ + if(ereg("::",$tmp2)) + { + $encoded = split("::",$entry); + $attr = $encoded[0]; + $value = base64_decode($encoded[1]); + /* Add linenumber */ + $data .= $current_line."#".$attr.":".$value."\n"; + } + else + { + /* Add Linenumber */ + $data .= $current_line."#".$entry."\n"; + } + } + } + } + + /* The Data we collected is not in the array all[]; + For example the Data is stored like this.. + + all[0] = "1#dn : .... \n + 2#ObjectType: person \n ...." + + Now we check every insertblock and try to insert */ + foreach ( $all as $single) { + $lineone = split("\n",$single); + $ndn = split("#", $lineone[0]); + $line = $ndn[1]; + + $dnn = split (":",$line); + $current_line = $ndn[0]; + $dn = $dnn[0]; + $value = $dnn[1]; + + /* Every block must begin with a dn */ + if($dn != "dn") { + $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), + $line, $current_line); + return -2; + } + + + // Should we use Modify instead of Add + $usemodify = false; + + // Delete before insert + $usermdir = false; + + + + /* The dn address already exists! */ + if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) { + $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line); + return ALREADY_EXISTING_ENTRY; + } + elseif(($this->dn_exists($value))&&($cleanup)){ + ;//Delete first, then add + $usermdir = true; + } + elseif(($this->dn_exists($value))&&($overwrite)) { + ;//Modify instead of Add + $usemodify = true; + } + + + /* If we can't Import, return with a file error */ + if(!$this->import_single_entry($single,$usemodify,$usermdir) ) { + $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line, + $current_line); + return UNKNOWN_TOKEN_IN_LDIF_FILE; } + + } + return (INSERT_OK); + } + + /* Imports a single entry */ + function import_single_entry($str_attr,$modify,$delete) + { + + + + if($this->reconnect) $this->connect(); + + $ret = false; + + $rows = split("\n",$str_attr); + $data = false; + foreach($rows as $row) { + + /* Check if we use Linenumbers (when import_complete_ldif is called we use + Linenumbers) Linenumbers are use like this 123#attribute : value */ + if(!empty($row)) { + if((strpos($row,"#")!=FALSE)&&(strpos($row,"#")cd($data['dn']); + + /* Delete existing entry */ + if($delete) + $this->rmdir($data['dn']); + + + /* Create missing trees */ + $this->create_missing_trees($data['dn']); + unset($data['dn']); + + /* If entry exists use modify */ + if(!$modify) + $ret = $this->add($data); + else + $ret = $this->modify($data); + + + + } + + return($ret); + } + + + function importcsv($str) + { + $lines = split("\n",$str); + foreach($lines as $line) + { + /* continue if theres a comment */ + if(substr(trim($line),0,1)=="#") + continue; + + $line= str_replace ("\t\t","\t",$line); + $line= str_replace ("\t" ,"," ,$line); + print $line; + + + + $cells = split(",",$line ) ; + #print_a($cells); + $linet= str_replace ("\t\t",",",$line); + $cells = split("\t",$line); + $count = count($cells); + } + + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_mail-methods-cyrus.inc b/include/class_mail-methods-cyrus.inc new file mode 100644 index 000000000..239cd2e8a --- /dev/null +++ b/include/class_mail-methods-cyrus.inc @@ -0,0 +1,317 @@ +config= $config->data['SERVERS']['IMAP']; + } + + function connect($gosaMailServer) + { + /* Connect to IMAP server. I don't want to see these warning here... */ + error_reporting (0); + $this->gosaMailServer= $gosaMailServer; + $cfg= $this->config[$gosaMailServer]; + $this->mbox = @imap_open($cfg['connect'], $cfg['admin'], $cfg['password'], OP_HALFOPEN); + error_reporting (E_ALL); + + /* Mailbox reachable? */ + if ($this->mbox === FALSE){ + print_red (_("Warning: IMAP Server cannot be reached! If you save this account, some mail settings will not be stored on your server!")); + return (FALSE); + } + return (TRUE); + } + + function disconnect() + { + imap_close ($this->mbox); + } + + function getQuota($folder) + { + $result= array('quotaUsage' => '', 'gosaMailQuota' => ''); + + /* Load quota settings */ + error_reporting (0); + $quota_value = @imap_get_quota($this->mbox, $folder); + if(is_array($quota_value)) { + if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){ + /* use for PHP >= 4.3 */ + $result['quotaUsage']= $quota_value["STORAGE"]['usage']; + $result['gosaMailQuota']= $quota_value["STORAGE"]['limit']; + } else { + /* backward compatible */ + $result['quotaUsage']= $quota_value['usage']; + $result['gosaMailQuota']= $quota_value['limit']; + } + } + error_reporting (E_ALL); + + return ($result); + } + + function getMailboxList($folder, $uid= "") + { + /* Initialize depending on group or user mode */ + if ($uid != ""){ + $result= array("INBOX"); + } else { + $result= array(); + } + + /* Get list of mailboxes for combo box */ + $cfg= $this->config[$this->gosaMailServer]; + $list = imap_listmailbox($this->mbox, $cfg["connect"], $folder.".*"); + if (is_array($list)){ + foreach ($list as $val){ + $result[]=preg_replace ("/.*user\.".$uid."\./", + "INBOX.", imap_utf7_decode ($val)); + } + } + + return ($result); + } + + function updateMailbox($folder) + { + /* Check if mailbox exists */ + $cfg= $this->config[$this->gosaMailServer]; + $list = imap_listmailbox($this->mbox, $cfg["connect"], $folder); + if ($list === FALSE){ + if (!imap_createmailbox($this->mbox, $cfg["connect"]. $folder)){ + print_red(sprintf(_("Can't create IMAP mailbox. Server says '%s'."), imap_last_error())); + return; + } + } + } + + + function setQuota($folder, $gosaMailQuota) + { + /* Workaround for the php imap extension */ + if ($gosaMailQuota == ""){ + $gosaMailQuota= "0"; + } + + /* Write mail quota */ + if (!imap_set_quota($this->mbox, $folder, $gosaMailQuota)){ + print_red(sprintf(_("Can't write IMAP quota. Server says '%s'."), imap_last_error())); + return (FALSE); + } + return (TRUE); + } + + + function setSharedFolderPermissions($folder, $permissions) + { + /* Show warning message in case of missing imap_getacl */ + if (!function_exists('imap_getacl')){ + print_red (_("Warning: imap_getacl is not implemented, wouldn't modify acl informations.")); + return; + } + + /* Get list of subfolders */ + $folders= $this->getMailboxList($folder, ""); + $folders[]= $folder; + + foreach ($folders as $subfolder){ + + /* Set shared folder acl's */ + if (function_exists('imap_getacl')){ + + /* Remove all acl's for this folder */ + $users= imap_getacl ($this->mbox, $subfolder); + foreach ($users as $userid => $perms){ + imap_setacl ($this->mbox, $subfolder, $userid, ""); + } + } + + /* Set permissions for this folder */ + foreach ($permissions as $user => $acl){ + imap_setacl ($this->mbox, $subfolder, $user, $acl); + } + } + + } + + + function getSharedFolderPermissions($folder) + { + $result= array(); + + /* imap_getacl available? */ + if (!function_exists('imap_getacl')){ + print_red (_("Warning: imap_getacl is not available, can't get imap permissions!")); + } + + /* Get permissions in case of shared folders */ + else { + $users= imap_getacl ($this->mbox, $folder); + + foreach ($users as $userid => $perms){ + $result[preg_replace('/^user\./', '', $userid)]= $perms; + } + + } + + return ($result); + } + + + function deleteMailbox($folder) + { + $cfg= $this->config[$this->gosaMailServer]; + imap_setacl ($this->mbox, $folder, $cfg["admin"], "lrswipcda"); + if (!imap_deletemailbox($this->mbox, $cfg["connect"].$folder)){ + print_red(sprintf(_("Can't remove IMAP mailbox. Server says '%s'."), imap_last_error())); + return (FALSE); + } + return (TRUE); + } + + + function configureFilter($user, $gosaMailDeliveryMode, + $mail, $gosaMailAlternateAddress, + $gosaMailMaxSize, + $gosaSpamMailbox, $gosaSpamSortLevel, + $gosaVacationMessage) + { + $cfg= $this->config[$this->gosaMailServer]; + + /* Build spamlevel. Spamassassin tags mails with "*" for each integer + point of spam. So a spam level of 5.3 gets "*****" which can be + checked easily by spam filters */ + $spamlevel= ""; + for ($i= 0; $i<$gosaSpamSortLevel; $i++){ + $spamlevel .= "*"; + } + + /* Log into the mail server */ + $sieve= new sieve($cfg["sieve_server"], $cfg["sieve_port"], $user, + $cfg["password"], $cfg["admin"]); + + if (!$sieve->sieve_login()){ + print_red(sprintf(_("Can't log into SIEVE server. Server says '%s'."), + to_string($sieve->error_raw))); + return; + } + + /* Load current script from server and remove everything between the comments + "###GOSA" */ + $script= ""; + if($sieve->sieve_listscripts()){ + if (in_array("gosa", $sieve->response)){ + + /* get old GOsa script */ + if(!$sieve->sieve_getscript("gosa")){ + print_red(sprintf(_("Can't get sieve script. Server says '%s'."), to_string($sieve->error_raw))); + return; + } + + foreach ($sieve->response as $line){ + if (preg_match ("/^###GOSA/", $line)){ + break; + } + $line= rtrim($line); + if (!preg_match ('/^\s*$/', $line)){ + $script .= $line."\n"; + } + } + + } + } + + /* Only create a new one, if it is not empty */ + if (is_integer(strpos($gosaMailDeliveryMode, "R")) || + is_integer(strpos($gosaMailDeliveryMode, "C")) || + !is_integer(strpos($gosaMailDeliveryMode, "L")) || + is_integer(strpos($gosaMailDeliveryMode, "V")) || + is_integer(strpos($gosaMailDeliveryMode, "S"))){ + + $text= preg_replace('/"/', '\\"', implode ("", file(CONFIG_DIR."/sieve-header.txt"))); + eval ("\$script.=\"$text\";"); + } + + /* Add anti-spam code */ + if (is_integer(strpos($gosaMailDeliveryMode, "S"))){ + $spambox= $gosaSpamMailbox; + $text= preg_replace('/"/', '\\"', implode ("", file(CONFIG_DIR."/sieve-spam.txt"))); + eval ("\$script.=\"$text\";"); + } + + /* Add "reject due to mailsize" code, message is currently not + adjustable through GOsa. */ + if (is_integer(strpos($gosaMailDeliveryMode, "R"))){ + $maxsize= $gosaMailMaxSize; + $text= preg_replace('/"/', '\\"', implode ("", file(CONFIG_DIR."/sieve-mailsize.txt"))); + eval ("\$script.=\"$text\";"); + } + + /* Add vacation information */ + if (is_integer(strpos($gosaMailDeliveryMode, "V"))){ + + /* Sieve wants all destination addresses for the + vacation message, so we've to assemble them from + mail and mailAlternateAddress */ + $addrlist= "\"".$mail."\""; + foreach ($gosaMailAlternateAddress as $val){ + $addrlist .= ", \"$val\""; + } + $vacmsg= $gosaVacationMessage; + $text= preg_replace('/"/', '\\"', implode ("", file(CONFIG_DIR."/sieve-vacation.txt"))); + eval ("\$script.=\"$text\";"); + } + + /* If no local delivery is wanted, tell the script to discard the mail */ + if (!is_integer(strpos($gosaMailDeliveryMode, "L"))){ + $text= preg_replace('/"/', '\\"', implode ("", file(CONFIG_DIR."/sieve-discard.txt"))); + eval ("\$script.=\"$text\";"); + } + + /* Just be aware of null scripts... */ + if (!isset ($script)){ + $script= ""; + } + + /* Upload script and make it the default one */ + if (!$sieve->sieve_sendscript("gosa", $script)){ + print_red(sprintf(_("Can't send sieve script. Server says '%s'."), to_string($sieve->error_raw))); + return; + } + if(!$sieve->sieve_setactivescript("gosa")){ + print_red(sprintf(_("Can't activate GOsa sieve script. Server says '%s'."), to_string($sieve->error_raw))); + return; + } + + $sieve->sieve_logout(); + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_mail-methods-kolab.inc b/include/class_mail-methods-kolab.inc new file mode 100644 index 000000000..4f28ecff6 --- /dev/null +++ b/include/class_mail-methods-kolab.inc @@ -0,0 +1,113 @@ + "alias", + "gosaMailQuota" => "cyrus-userquota", + "gosaMailServer" => "kolabHomeServer"); + + function mailMethodKolab($config) + { + $this->config= $config->data['SERVERS']['IMAP']; + } + + function updateMailbox($folder) + { + } + + function setQuota($folder, $gosaMailQuota) + { + return (TRUE); + } + + function setSharedFolderPermissions($folder, $permissions) + { + } + + function deleteMailbox($folder) + { + return (TRUE); + } + + + function fixAttributesOnLoad(&$mailObject) + { + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $dest => $source){ + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + } + } + + /* Adjust server name if needed */ + foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){ + if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){ + $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1); + break; + } + } + } + + + function fixAttributesOnStore(&$mailObject) + { + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $source => $dest){ + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + } + } + $objectclasses= array(); + foreach ($mailObject->attrs['objectClass'] as $oc){ + if ($oc != 'kolabInetOrgPerson'){ + $objectclasses[]= $oc; + } + } + $mailObject->attrs['objectClass']= $objectclasses; + $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson'; + + /* Remove imap:// tagging */ + $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']); + $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer']; + $mailObject->attrs['kolabDeleteFlag']= array(); + } + + + function fixAttributesOnRemove(&$mailObject) + { + /* Add attribute for object deletion and remove GOsa specific + values from entry. */ + unset ($mailObject->attrs['mail']); + $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer); + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_mail-methods-sendmail-cyrus.inc b/include/class_mail-methods-sendmail-cyrus.inc new file mode 100644 index 000000000..f8cb7c3de --- /dev/null +++ b/include/class_mail-methods-sendmail-cyrus.inc @@ -0,0 +1,53 @@ +config= $config->data['SERVERS']['IMAP']; + } + + function fixAttributesOnLoad(&$mailObject) + { + /* Remove possible local alias from forwarders */ + $newForwarder= array(); + foreach ($mailObject->gosaMailForwardingAddress as $addr){ + if (!preg_match('/^\\\\/', $addr)){ + $newForwarder[]= $addr; + } + } + $mailObject->gosaMailForwardingAddress= $newForwarder; + } + + function fixAttributesOnStore(&$mailObject) + { + /* Add local user if checked */ + if (preg_match("/L/", $mailObject->gosaMailDeliveryMode)) { + $mailObject->gosaMailForwardingAddress[]= "\\".$mailObject->uid; + } + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_mail-methods.inc b/include/class_mail-methods.inc new file mode 100644 index 000000000..2e67f7eaa --- /dev/null +++ b/include/class_mail-methods.inc @@ -0,0 +1,90 @@ + 0, 'gosaMailQuota' => 0)); + } + + function getMailboxList($folder, $uid) + { + return (array("INBOX")); + } + + function setQuota($folder, $gosaMailQuota) + { + return (TRUE); + } + + function updateMailbox($folder) + { + } + + function deleteMailbox($folder) + { + return (TRUE); + } + + function setSharedFolderPermissions($folder, $permissions) + { + } + + function configureFilter($user, $gosaMailDeliveryMode, + $mail, $gosaMailAlternateAddress, + $gosaMailMaxSize, + $gosaSpamMailbox, $gosaSpamSortLevel, + $gosaVacationMessage) + { + } + + function fixAttributesOnLoad(&$mailObject) + { + } + + function fixAttributesOnStore(&$mailObject) + { + } + + function fixAttributesOnRemove(&$mailObject) + { + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_password-methods-clear.inc b/include/class_password-methods-clear.inc new file mode 100644 index 000000000..e4d28e993 --- /dev/null +++ b/include/class_password-methods-clear.inc @@ -0,0 +1,41 @@ + diff --git a/include/class_password-methods-crypt.inc b/include/class_password-methods-crypt.inc new file mode 100644 index 000000000..c3d21c8b4 --- /dev/null +++ b/include/class_password-methods-crypt.inc @@ -0,0 +1,44 @@ + diff --git a/include/class_password-methods-kerberos.inc b/include/class_password-methods-kerberos.inc new file mode 100644 index 000000000..1e8ba722d --- /dev/null +++ b/include/class_password-methods-kerberos.inc @@ -0,0 +1,72 @@ +config->data['SERVERS']['KERBEROS']; + + if (!function_exists('kadm5_init_with_password')) + { + print_red (_("Warning: Can't set kerberos password. Your PHP version has no kerberos support, password has not been changed.")); + } + else + { + $handle = kadm5_init_with_password($cfg['SERVER'], + $cfg['REALM'], $cfg['ADMIN'], $cfg['PASSWORD']); + + if ($handle === FALSE) + { + print_red (_("Kerberos database communication failed!")); + } + + $ret= kadm5_chpass_principal($handle, $attrs['uid'][0]."@".$cfg['REALM'],$password); + + if ($ret === FALSE) + { + print_red (_("Changing password in kerberos database failed!")); + } + + kadm5_destroy($handle); + + $newpass= "{kerberos}".$attrs['uid'][0]."@".$cfg['REALM']; + + return $newpass; + } + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_password-methods-md5.inc b/include/class_password-methods-md5.inc new file mode 100644 index 000000000..b27103692 --- /dev/null +++ b/include/class_password-methods-md5.inc @@ -0,0 +1,46 @@ + diff --git a/include/class_password-methods-sha.inc b/include/class_password-methods-sha.inc new file mode 100644 index 000000000..0780a76e0 --- /dev/null +++ b/include/class_password-methods-sha.inc @@ -0,0 +1,59 @@ + diff --git a/include/class_password-methods-smd5.inc b/include/class_password-methods-smd5.inc new file mode 100644 index 000000000..fea58f699 --- /dev/null +++ b/include/class_password-methods-smd5.inc @@ -0,0 +1,48 @@ + diff --git a/include/class_password-methods-ssha.inc b/include/class_password-methods-ssha.inc new file mode 100644 index 000000000..e80e56651 --- /dev/null +++ b/include/class_password-methods-ssha.inc @@ -0,0 +1,59 @@ + diff --git a/include/class_password-methods.inc b/include/class_password-methods.inc new file mode 100644 index 000000000..97157804e --- /dev/null +++ b/include/class_password-methods.inc @@ -0,0 +1,219 @@ +generate_hash($string); + return( $newpass); + } + + + // this function returns all loaded classes for password encryption + function get_available_methods() + { + $ret =false; + $all = (get_declared_classes()); + $i = 0; + foreach($all as $one) { + if((strstr($one,"passwordmethod" ))&&($one != "passwordmethod")){ + $name = str_replace ("passwordmethod","",$one); + $test = new $one(false); + if($test->is_available()) { + $ret['name'][$i]=str_replace ("passwordmethod","",$one); + $ret['class'][$i]=$one; + $ret[$i]['name']=str_replace ("passwordmethod","",$one); + $ret[$i]['class']=$one; + $ret[str_replace ("passwordmethod","",$one)]=$one; + $i++; + } + } + } + return($ret); + } + +} + +// change_password, changes the Password, of the given dn +function change_password ($dn, $password, $mode=0, $hash= "") +{ + + global $config; + $newpass= ""; + + + // Get all available encryption Methods + $available = passwordMethod::get_available_methods(); + + + // read current password entry for $dn, to detect the encryption Method + $ldap = $config->get_ldap_link(); + $ldap->cat ($dn); + $attrs = $ldap->fetch (); + + // Set encryption type to clear if required + if (isset($attrs['userPassword'][0]) && preg_match('/^[^{}]+$/', $attrs['userPassword'][0]) && $hash == ""){ + $hash= "clear"; + } + + + + // Detect the encryption Method + if ( (isset($attrs['userPassword'][0]) && preg_match ("/^{([^}]+)}(.+)/", $attrs['userPassword'][0], $matches)) || $hash != ""){ + + /* Check for supported algorithm */ + mt_srand((double) microtime()*1000000); + + /* Extract used hash */ + if ($hash == ""){ + $hash= strtolower($matches[1]); + } + + + // Crypt with the detected Method + $test = new $available[$hash]($config); + $newpass = $test->generate_hash($password); + + } else { + // Crypt it by default + $test = new $available['md5']($config); + $newpass = $test->generate_hash($password); + } + + + + // Update shadow timestamp? + if (isset($attrs["shadowLastChange"][0])){ + $shadow= (int)(date("U") / 86400); + } else { + $shadow= 0; + } + + // Write back modified entry + $ldap->cd($dn); + $attrs= array(); + + // Not for groups + if ($mode == 0){ + + if ($shadow != 0){ + $attrs['shadowLastChange']= $shadow; + } + + // Create SMB Password + $attrs = generate_smb_nt_hash($password); + } + + $attrs['userPassword']= array(); + $attrs['userPassword']= $newpass; + + + $ldap->modify($attrs); + + + if ($ldap->error != 'Success') + { + print_red(sprintf(_("Setting the password failed. LDAP server says '%s'."), + $ldap->get_error())); + } +} + + +// Retrun something like array['sambaLMPassword']= "lalla..." +function generate_smb_nt_hash($password) +{ + global $config; + $tmp= $config->data['MAIN']['SMBHASH']." ".escapeshellarg($password); + @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__, $tmp, "Execute"); + + exec($tmp, $ar); + flush(); + reset($ar); + $hash= current($ar); + if ($hash == "") + { + print_red (_("Setting for SMBHASH in gosa.conf is incorrect! Can't change Samba password.")); + } + else + { + list($lm,$nt)= split (":", trim($hash)); + + if ($config->current['SAMBAVERSION'] == 3) + { + $attrs['sambaLMPassword']= $lm; + $attrs['sambaNTPassword']= $nt; + $attrs['sambaPwdLastSet']= date('U'); + $attrs['sambaBadPasswordCount']= "0"; + $attrs['sambaBadPasswordTime']= "0"; + } else { + $attrs['lmPassword']= $lm; + $attrs['ntPassword']= $nt; + $attrs['pwdLastSet']= date('U'); + } + return($attrs); + } +} + +function crypt_single($string,$enc_type ) +{ + if(!class_exists("passwordMethod")){ + require_once("class_password-methods.inc"); + } + return( passwordMethod::crypt_single_str($string,$enc_type)); +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_plugin.inc b/include/class_plugin.inc new file mode 100644 index 000000000..5fd4220f0 --- /dev/null +++ b/include/class_plugin.inc @@ -0,0 +1,682 @@ + + \version 2.00 + \date 24.07.2003 + + This is the base class for all plugins. It can be used standalone or + can be included by the tabs class. All management should be done + within this class. Extend your plugins from this class. + */ + +class plugin +{ + /*! + \brief Reference to parent object + + This variable is used when the plugin is included in tabs + and keeps reference to the tab class. Communication to other + tabs is possible by 'name'. So the 'fax' plugin can ask the + 'userinfo' plugin for the fax number. + + \sa tab + */ + var $parent= NULL; + + /*! + \brief Configuration container + + Access to global configuration + */ + var $config= NULL; + + /*! + \brief Mark plugin as account + + Defines whether this plugin is defined as an account or not. + This has consequences for the plugin to be saved from tab + mode. If it is set to 'FALSE' the tab will call the delete + function, else the save function. Should be set to 'TRUE' if + the construtor detects a valid LDAP object. + + \sa plugin::plugin() + */ + var $is_account= FALSE; + var $initially_was_account= FALSE; + + /*! + \brief Mark plugin as template + + Defines whether we are creating a template or a normal object. + Has conseqences on the way execute() shows the formular and how + save() puts the data to LDAP. + + \sa plugin::save() plugin::execute() + */ + var $is_template= FALSE; + var $ignore_account= FALSE; + var $is_modified= FALSE; + + /*! + \brief Represent temporary LDAP data + + This is only used internally. + */ + var $attrs= array(); + + + /*! + \brief Used standard values + + dn + */ + var $dn= ""; + var $uid= ""; + var $sn= ""; + var $givenName= ""; + var $acl= "*none*"; + var $dialog= FALSE; + + /* attribute list for save action */ + var $attributes= array(); + var $objectclasses= array(); + var $new= TRUE; + + /*! \brief plugin constructor + + If 'dn' is set, the node loads the given 'dn' from LDAP + + \param dn Distinguished name to initialize plugin from + \sa plugin() + */ + function plugin ($config, $dn= NULL) + { + /* Configuration is fine, allways */ + $this->config= $config; + $this->dn= $dn; + + /* Handle new accounts, don't read information from LDAP */ + if ($dn == "new"){ + return; + } + + /* Get LDAP descriptor */ + $ldap= $this->config->get_ldap_link(); + if ($dn != NULL){ + + /* Load data to 'attrs' and save 'dn' */ + $ldap->cat ($dn); + $this->attrs= $ldap->fetch(); + + /* Copy needed attributes */ + foreach ($this->attributes as $val){ + if (isset($this->attrs["$val"][0])){ + $this->$val= $this->attrs["$val"][0]; + } + } + + /* Set the template flag according to the existence of objectClass + gosaUserTemplate */ + if (isset($this->attrs['objectClass'])){ + if (in_array ("gosaUserTemplate", $this->attrs['objectClass'])){ + $this->is_template= TRUE; + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + "found", "Template check"); + } + } + + /* Is Account? */ + error_reporting(0); + $found= TRUE; + foreach ($this->objectclasses as $obj){ + if (preg_match('/top/i', $obj)){ + continue; + } + if (!in_array_ics ($obj, $this->attrs['objectClass'])){ + $found= FALSE; + break; + } + } + error_reporting(E_ALL); + if ($found){ + $this->is_account= TRUE; + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + "found", "Object check"); + } + } + + /* Save initial account state */ + $this->initially_was_account= $this->is_account; + } + + /*! \brief execute plugin + + Generates the html output for this node + */ + function execute() + { + /* Do we represent a valid account? */ + if (!$this->is_account){ + echo " ". + _("This 'dn' has no account extensions.").""; + return; + } + + /* Show dummy message */ + echo _("This is an empty plugin."); + } + + /* remove object from parent */ + function remove_from_parent() + { + /* include global link_info */ + $ldap= $this->config->get_ldap_link(); + + /* Get current objectClasses in order to add the required ones */ + $ldap->cat($this->dn); + $tmp= $ldap->fetch (); + if (isset($tmp['objectClass'])){ + $oc= $tmp['objectClass']; + } else { + $oc= array("count" => 0); + } + + /* Remove objectClasses from entry */ + $ldap->cd($this->dn); + $this->attrs= array(); + $this->attrs['objectClass']= array(); + for ($i= 0; $i<$oc["count"]; $i++){ + if (!in_array_ics($oc[$i], $this->objectclasses)){ + $this->attrs['objectClass'][]= $oc[$i]; + } + } + + /* Unset attributes from entry */ + foreach ($this->attributes as $val){ + $this->attrs["$val"]= array(); + } + + /* Unset account info */ + $this->is_account= FALSE; + + /* Do not write in plugin base class, this must be done by + children, since there are normally additional attribs, + lists, etc. */ + /* + $ldap->modify($this->attrs); + */ + } + + + /* Save data to object */ + function save_object() + { + /* Save values to object */ + foreach ($this->attributes as $val){ + if (chkacl ($this->acl, "$val") == "" && isset ($_POST["$val"])){ + + /* Check for modifications */ + if (get_magic_quotes_gpc()) { + $data= stripcslashes($_POST["$val"]); + } else { + $data= $this->$val = $_POST["$val"]; + } + if ($this->$val != $data){ + $this->is_modified= TRUE; + } + $this->$val= $data; + } + } + } + + + /* Save data to LDAP, depending on is_account we save or delete */ + function save() + { + /* include global link_info */ + $ldap= $this->config->get_ldap_link(); + + /* Start with empty array */ + $this->attrs= array(); + + /* Get current objectClasses in order to add the required ones */ + $ldap->cat($this->dn); + + $tmp= $ldap->fetch (); + + if (isset($tmp['objectClass'])){ + $oc= $tmp["objectClass"]; + $this->new= FALSE; + } else { + $oc= array("count" => 0); + $this->new= TRUE; + } + + /* Load (minimum) attributes, add missing ones */ + $this->attrs['objectClass']= $this->objectclasses; + for ($i= 0; $i<$oc["count"]; $i++){ + if (!in_array_ics($oc[$i], $this->objectclasses)){ + $this->attrs['objectClass'][]= $oc[$i]; + } + } + + /* Copy standard attributes */ + foreach ($this->attributes as $val){ + if ($this->$val != ""){ + $this->attrs["$val"]= $this->$val; + } elseif (!$this->new) { + $this->attrs["$val"]= array(); + } + } + + } + + /* Check formular input */ + function check() + { + $message= array(); + return ($message); + } + + /* Adapt from template, using 'dn' */ + function adapt_from_template($dn) + { + /* Include global link_info */ + $ldap= $this->config->get_ldap_link(); + + /* Load requested 'dn' to 'attrs' */ + $ldap->cat ($dn); + $this->attrs= $ldap->fetch(); + + /* Walk through attributes */ + foreach ($this->attributes as $val){ + + if (isset($this->attrs["$val"][0])){ + + /* If attribute is set, replace dynamic parts: + %sn, %givenName and %uid. Fill these in our local variables. */ + $value= $this->attrs["$val"][0]; + + foreach (array("sn", "givenName", "uid") as $repl){ + if (preg_match("/%$repl/i", $value)){ + $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value); + } + } + $this->$val= $value; + } + } + + /* Is Account? */ + $found= TRUE; + foreach ($this->objectclasses as $obj){ + if (preg_match('/top/i', $obj)){ + continue; + } + if (!in_array_ics ($obj, $this->attrs['objectClass'])){ + $found= FALSE; + break; + } + } + if ($found){ + $this->is_account= TRUE; + } + } + + /* Indicate whether a password change is needed or not */ + function password_change_needed() + { + return FALSE; + } + + /* Show header message for tab dialogs */ + function show_header($button_text, $text, $disabled= FALSE) + { + if ($disabled == TRUE){ + $state= "disabled"; + } else { + $state= ""; + } + $display= "\n

$text

\n"; + $display.= "acl, "all")." ".$state. + ">

 

"; + + return($display); + } + + function postcreate() + { + /* Find postcreate entries for this class */ + $command= $this->search($this->config->data['MENU'], get_class($this), "POSTCREATE"); + if ($command == ""){ + $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTCREATE"); + } + + if ($command != ""){ + /* Walk through attribute list */ + foreach ($this->attributes as $attr){ + $command= preg_replace("/%$attr/", $this->$attr, $command); + } + $command= preg_replace("/%dn/", $this->dn, $command); + if (check_command($command)){ + @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, + $command, "Execute"); + + exec($command); + } else { + $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this)); + print_red ($message); + } + } + } + + function postmodify() + { + /* Find postcreate entries for this class */ + $command= $this->search($this->config->data['MENU'], get_class($this), "POSTMODIFY"); + if ($command == ""){ + $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTMODIFY"); + } + + if ($command != ""){ + /* Walk through attribute list */ + foreach ($this->attributes as $attr){ + $command= preg_replace("/%$attr/", $this->$attr, $command); + } + $command= preg_replace("/%dn/", $this->dn, $command); + if (check_command($command)){ + @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, + $command, "Execute"); + + exec($command); + } else { + $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this)); + print_red ($message); + } + } + } + + function postremove() + { + /* Find postremove entries for this class */ + $command= $this->search($this->config->data['MENU'], get_class($this), "POSTREMOVE"); + if ($command == ""){ + $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTREMOVE"); + } + + if ($command != ""){ + /* Walk through attribute list */ + foreach ($this->attributes as $attr){ + $command= preg_replace("/%$attr/", $this->$attr, $command); + } + $command= preg_replace("/%dn/", $this->dn, $command); + if (check_command($command)){ + @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, + $command, "Execute"); + + exec($command); + } else { + $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this)); + print_red ($message); + } + } + } + + function search($arr, $name, $return) + { + if (is_array($arr)){ + foreach ($arr as $a){ + if (isset($a['CLASS']) && + strtolower($a['CLASS']) == strtolower($name)){ + + if (isset($a[$return])){ + return ($a[$return]); + } else { + return (""); + } + } else { + $res= $this->search ($a, $name, $return); + if ($res != ""){ + return $res; + } + } + } + } + return (""); + } + + /* Create unique DN */ + function create_unique_dn($attribute, $base) + { + $ldap= $this->config->get_ldap_link(); + $base= preg_replace("/^,*/", "", $base); + + /* Try to use plain entry first */ + $dn= "$attribute=".$this->$attribute.",$base"; + $ldap->cat ($dn); + if (!$ldap->fetch()){ + return ($dn); + } + + /* Look for additional attributes */ + foreach ($this->attributes as $attr){ + if ($attr == $attribute || $this->$attr == ""){ + continue; + } + + $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base"; + $ldap->cat ($dn); + if (!$ldap->fetch()){ + return ($dn); + } + } + + /* None found */ + return ("none"); + } + + function rebind($ldap, $referral) + { + $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']); + if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) { + $this->error = "Success"; + $this->hascon=true; + $this->reconnect= true; + return (0); + } else { + $this->error = "Could not bind to " . $binddn; + return NULL; + } + } + + /* This is a workaround function. */ + function copy($src_dn, $dst_dn) + { + /* Rename dn in possible object groups */ + $ldap= $this->config->get_ldap_link(); + $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.$src_dn.'))', + array('cn')); + while ($attrs= $ldap->fetch()){ + $og= new ogroup($this->config, $ldap->getDN()); + unset($og->member[$src_dn]); + $og->member[$dst_dn]= $dst_dn; + $og->save (); + } + + $ldap->cat($dst_dn); + $attrs= $ldap->fetch(); + if (count($attrs)){ + trigger_error("Trying to overwrite $dst_dn, which already exists.", + E_USER_WARNING); + return (FALSE); + } + + $ldap->cat($src_dn); + $attrs= array(); + $attrs= $ldap->fetch(); + if (!count($attrs)){ + trigger_error("Trying to move $src_dn, which does not seem to exist.", + E_USER_WARNING); + return (FALSE); + } + + /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */ + $ds= ldap_connect($this->config->current['SERVER']); + ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); + if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) { + ldap_set_rebind_proc($ds, array(&$this, "rebind")); + } + + $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']); + error_reporting (0); + $sr=ldap_read($ds, $src_dn, "objectClass=*"); + + /* Fill data from LDAP */ + $new= array(); + if ($sr) { + $ei=ldap_first_entry($ds, $sr); + if ($ei) { + foreach($attrs as $attr => $val){ + if ($info = ldap_get_values_len($ds, $ei, $attr)){ + for ($i= 0; $i<$info['count']; $i++){ + if ($info['count'] == 1){ + $new[$attr]= $info[$i]; + } else { + $new[$attr][]= $info[$i]; + } + } + } + } + } + } + + /* close conncetion */ + error_reporting (E_ALL); + ldap_unbind($ds); + + /* Adapt naming attribute */ + $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn); + $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn); + $new[$dst_name]= $dst_val; + + /* Save copy */ + $ldap->connect(); + $ldap->cd($this->config->current['BASE']); + $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn)); + $ldap->cd($dst_dn); + $ldap->add($new); + + if ($ldap->error != "Success"){ + trigger_error("Trying to save $dst_dn failed.", + E_USER_WARNING); + return(FALSE); + } + + return (TRUE); + } + + + function move($src_dn, $dst_dn) + { + /* Copy source to destination */ + if (!$this->copy($src_dn, $dst_dn)){ + return (FALSE); + } + + /* Delete source */ + $ldap= $this->config->get_ldap_link(); + $ldap->rmdir($src_dn); + if ($ldap->error != "Success"){ + trigger_error("Trying to delete $src_dn failed.", + E_USER_WARNING); + return (FALSE); + } + + return (TRUE); + } + + + /* Move/Rename complete trees */ + function recursive_move($src_dn, $dst_dn) + { + /* Check if the destination entry exists */ + $ldap= $this->config->get_ldap_link(); + + /* Check if destination exists - abort */ + $ldap->cat($dst_dn); + if ($ldap->fetch()){ + trigger_error("recursive_move $dst_dn already exists.", + E_USER_WARNING); + return (FALSE); + } + + /* Perform a search for all objects to be moved */ + $objects= array(); + $ldap->cd($src_dn); + $ldap->search("(objectClass=*)", array("dn")); + while($attrs= $ldap->fetch()){ + $dn= $attrs['dn']; + $objects[$dn]= strlen($dn); + } + + /* Sort objects by indent level */ + asort($objects); + reset($objects); + + /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */ + foreach ($objects as $object => $len){ + $src= $object; + $dst= preg_replace("/$src_dn$/", "$dst_dn", $object); + if (!$this->copy($src, $dst)){ + return (FALSE); + } + } + + /* Remove src_dn */ + $ldap->cd($src_dn); + $ldap->recursive_remove(); + return (TRUE); + } + + + function handle_post_events($mode) + { + switch ($mode){ + case "add": + $this->postcreate(); + break; + + case "modify": + $this->postmodify(); + break; + + case "remove": + $this->postremove(); + break; + } + } + + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/class_pluglist.inc b/include/class_pluglist.inc new file mode 100644 index 000000000..f6963d10f --- /dev/null +++ b/include/class_pluglist.inc @@ -0,0 +1,259 @@ +ui= $ui; + $this->config= $config; + + /* Create dirlist for all plugins */ + $this->dirlist= $this->get_plugins ($this->dirlist, $this->config->data); + } + + function get_plugins($list, $config) + { + /* Error reporting, because I'm getting strange messages in PHP 4.2.x */ + error_reporting(0); + if (!isset($config['PATH']) && !isset($config['CLASS'])){ + if (is_array($config)){ + foreach ($config as $val){ + $list= $this->get_plugins($list, $val); + } + } + } else { + if (isset ($config['PATH']) && is_array($config)){ + $list[$this->index++]= $config['PATH']; + } + } + error_reporting(E_ALL); + + return ($list); + } + + function check_access($modname) + { + /* This plugin is readable for everyone, return true */ + if ($modname == 'default'){ + return (TRUE); + } + + /* Look through ACL's */ + foreach($this->ui->subtreeACL as $arr){ + foreach($arr as $value){ + if ($value == ':all' || preg_match("/[,:]$modname#/", $value)){ + if (!preg_match('/^!/', $value)){ + return (TRUE); + } + } + } + } + + return (FALSE); + } + + function gen_menu() + { + if ($this->menu == ""){ + $cfg= $this->config->data['MENU']; + + /* Parse headlines */ + foreach ($cfg as $headline => $plug){ + $menu= "

"._($headline)."

\n"; + $entries= ""; + $this->menuparts[_($headline)]= array(); + + /* Parse sub-plugins */ + foreach ($plug as $info){ + + /* Read information from class variable */ + if (!isset($info['CLASS'])){ + print_red(_("Your gosa.conf information has changed partly. Please convert it using the contributed script fix_config.sh!")); + echo $_SESSION['errors']; + exit; + } + $vars= get_class_vars($info['CLASS']); + $plHeadline= $vars['plHeadline']; + $plDescription= $vars['plDescription']; + + $index= $this->get_index($info['PATH']); + $image= get_template_path('images/'.$info['ICON']); + $href= "main.php?plug=$index&reset=1"; + + if ($this->check_access($info['ACL'])){ + + $entries= $entries."

". + "". + _($plHeadline)."

\n"; + + /* Generate icon entry with description */ + $this->menuparts[_($headline)][]= ''; + + } + } + + /* Append to menu */ + if ($entries != ""){ + $this->menu.= $menu.$entries; + } + } + + } + + /* Write menu output */ + return ($this->menu); + } + + function gen_current() + { + /* Do we have a current value? */ + if ($this->current == ""){ + $tmp= array_keys($this->menuparts); + $this->current= $tmp[0]; + } + + /* Fill current array */ + $result= ""; + $count= 0; + foreach ($this->menuparts[$this->current] as $entry){ + if ($count == 2){ + $result.= ""; + $count= 0; + } + if ($count == 0){ + $result.= ""; + } + $result.= ""; + $count++; + } + + /* Add missing cell? */ + if ($count == 1){ + $result.= ""; + } + + $result.= "
$entry 
"; + return $result; + } + + + function show_iconmenu() + { + if ($this->iconmenu == ""){ + $cfg= $this->config->data['MENU']; + + if (isset($this->config->current['ICONSIZE'])){ + list($x, $y)= split("x", $this->config->current['ICONSIZE']); + $isize= "width=\"$x\" height=\"$y\""; + } else { + $isize= ""; + } + + /* Parse headlines */ + foreach ($cfg as $headline => $plug){ + $col= 1; + $menu= "

". + _($headline)."

\n\n\n"; + $entries= ""; + + foreach ($plug as $info){ + + /* Read information from class variable */ + $vars= get_class_vars($info['CLASS']); + $plHeadline= $vars['plHeadline']; + $plDescription= $vars['plDescription']; + + $index= $this->get_index($info['PATH']); + + if ($this->check_access($info['ACL'])){ + + /* next row? */ + $image= get_template_path('images/'.$info['ICON']); + if ($col % 5){ + $entries= $entries."\n"; + $col++; + } else { + $entries= $entries."\n\n\n"; + $col= 1; + } + } + } + + /* Append to menu */ + if ($entries != ""){ + $this->iconmenu.= $menu.$entries; + + /* Fill up remaining columns */ + if ($col != 1){ + $col--; + while ($col % 5){ + $this->iconmenu= $this->iconmenu. + "\n"; + $col++; + } + } + + /* close table */ + $this->iconmenu= $this->iconmenu."\n
". + "\"*\" ". + _($plHeadline)."". + "\"*\" ". + _($plHeadline)."
 
\n"; + } + } + + } + + /* Write menu output */ + return ($this->iconmenu); + } + + function get_path($index) + { + if(!isset($this->dirlist[$index])){ + return (""); + } + return ("../".$this->dirlist[$index]); + } + + function get_index($path) + { + return (array_search($path, $this->dirlist)); + } +} + +?> diff --git a/include/class_sambaMungedDial.inc b/include/class_sambaMungedDial.inc new file mode 100644 index 000000000..82b514be3 --- /dev/null +++ b/include/class_sambaMungedDial.inc @@ -0,0 +1,546 @@ + '551e0bb0', + 'CtxCfgFlags1'=> '00e00010', + 'CtxCallback'=> '0000000e', + 'CtxShadow'=> '01000000', + 'CtxKeyboardLayout' => '00000000', + 'CtxMinEncryptionLevel' => '', + 'CtxWorkDirectory' => '', + 'CtxNWLogonServer' => '', + 'CtxWFHomeDir' => '', + 'CtxWFHomeDirDrive' => '', + 'CtxWFProfilePath' => '', + 'CtxInitialProgram' => '', + 'CtxCallbackNumber' => ''); + + /* attribute list for save action */ + var $ctxattributes= array("CtxCfgPresent", "CtxCfgFlags1", "CtxCallback", + "CtxMaxConnectionTime", "CtxMaxDisconnectionTime", + "CtxMaxIdleTime", "CtxKeyboardLayout", "CtxMinEncryptionLevel", + "CtxWorkDirectory", "CtxNWLogonServer", "CtxWFHomeDir", + "CtxWFHomeDirDrive", "CtxWFProfilePath", "CtxInitialProgram", + "CtxCallbackNumber"); + + /* These parameters are treated as strings and get a trailing zero */ + var $stringParams= array( "CtxWorkDirectory", "CtxNWLogonServer", + "CtxWFHomeDir", "CtxWFHomeDirDrive", + "CtxWFProfilePath", "CtxInitialProgram", "CtxCallbackNumber"); + + /* These parameters are treated as time values and get converted */ + var $timeParams= array("CtxMaxConnectionTime", "CtxMaxDisconnectionTime", "CtxMaxIdleTime"); + + + function strhex($string) + { + $hex=""; + for ($i=0; $i> 16); + return (sambaMungedDial::endian(substr($src, 0, 4)).sambaMungedDial::endian(substr($src, 4, 4))); + } + + function readTime ($time) + { + $lo= substr($time, 0, 4); + $hi= substr($time, 4, 4); + + $usecs= (hexdec(substr($lo, 2, 2)) * 256 + hexdec(substr($lo, 0, 2))) + + (hexdec(substr($hi, 2 ,2)) * 256 + hexdec(substr($hi, 0, 2))) * 256 * 256; + + return ((int)($usecs / (60 * 1000))); + } + + function to8bit($string) + { + $result= ""; + + /* Strip zeros */ + for ($i= 0; $i $paramValue) { + + /* String parameter? */ + if (in_array($paramName, $this->stringParams)){ + $isString= TRUE; + $paramValue= sambaMungedDial::strhex($paramValue.chr(0).chr(0)); + } else { + $isString= FALSE; + } + + /* Time parameter? */ + if (in_array($paramName, $this->timeParams)){ + $paramValue= sambaMungedDial::genTime($paramValue); + } + + $result.= sambaMungedDial::munge($paramName, $paramValue, $isString); + } + + return ($result); + } + + /* Setup parameter given by paramName to MungedDial-Format */ + function munge($paramName, $paramValue, $isString) + { + $result= ""; + + /* Encode paramName to UTF-16 */ + if (function_exists("recode")){ + $utfName= recode("ISO8859-15..UTF-16", $paramName); + } else { + $utfName= iconv("ISO8859-15", "UTF-16BE", $paramName); + } + + /* Set parameter length, high and low byte */ + $paramLen= strlen($utfName); + $result.= chr($paramLen & 0x0FF); + $result.= chr(($paramLen & 0x0FF00) >> 8); + + /* String parameters have additional trailing bytes */ + $valueLen= strlen($paramValue); + $result.= chr($valueLen & 0x0FF); + $result.= chr(($valueLen & 0x0FF00) >> 8); + + /* Length fields have a trailing '01' appended by the UTF-16 converted name */ + $result.= chr(1); + $result.= $utfName; + + /* Parameter is padded with '00' */ + $result.= chr(0); + $result.= $paramValue; + + /* Append a trailing '00' to string parameters */ + if ($isString && (strlen($paramValue) & 1)){ + $result.= chr(0); + } + + return ($result); + } + + /* Takes a base64-encoded MungedDial-String and returns an array of included parameters and values */ + function decode_munged($munge) + { + $result= array(); + + /* Remove base64 encoding and skip FILEHEADER */ + $ctxField= substr(base64_decode($munge), strlen(FILEHEADER) / 2); + + /* Decode parameters */ + while ($ctxField!=""){ + + /* Read value lengths */ + $ctxParmNameLength= ord($ctxField[0]) + 16 * ord($ctxField[1]); + $ctxParmLength= ord($ctxField[2]) + 16 * ord($ctxField[3]); + + /* Reposition ctxField on start of parameter name, read parameter name */ + $ctxField= substr($ctxField, 6); + $ctxParmName= sambaMungedDial::to8bit(substr($ctxField, 0, $ctxParmNameLength)); + + /* Reposition ctxField on start of parameter */ + $ctxField= substr($ctxField, $ctxParmNameLength); + $ctxParm= substr($ctxField, 0, $ctxParmLength); + + /* If string parameter, convert */ + if (in_array($ctxParmName, $this->stringParams)){ + $ctxParm= sambaMungedDial::hexstr($ctxParm); + } + /* If time parameter, convert */ + if (in_array($ctxParmName, $this->timeParams)){ + $ctxParm= sambaMungedDial::readTime($ctxParm); + } + + /* Assign in result array */ + $result[$ctxParmName]= trim($ctxParm); + + /* Reposition ctxField on end of parameter and continue */ + $ctxField= substr($ctxField, $ctxParmLength); + } + + return ($result); + } + + /* function takes a base64-encoded sambaMungedDial */ + function load ($mungedDial) + { + $this->ctx= $this->decode_munged($mungedDial); + } + + /* Returns ready-to-run mungedDialString to be filled into ldap */ + function getMunged () + { + // Do extra check for valid timeParams (they must be set to 0 if disabled) + foreach($this->timeParams as $value) { + if(!isset($this->ctx[$value])) { + $this->ctx[$value]= 0; + } + } + $result= base64_encode($this->encode_munged($this->ctx)); + return $result; + } + + /* Returns array of flags, which can be set on-demand with activated java-script */ + function getOnDemandFlags () + { + $result= array(); + if ($_SESSION["js"]){ + foreach ($this->timeParams as $value) { + if (!isset($this->ctx[$value]) || (isset($this->ctx[$value]) && $this->ctx[$value] == 0)) { + $result[$value."Mode"]= "disabled"; + } + } + + if (substr($this->ctx['CtxCfgFlags1'], 6, 1) == "1") { + $result['CtxInitialProgramMode'] = "disabled"; + } + } + + return $result; + } + + /*Gets Terminal-Server-Login value: enabled/disabled */ + function getTsLogin () + { + $flags= ord(substr($this->ctx['CtxCfgFlags1'], 5, 1)); + + if ($flags & 1) { + $result= false; + } else { + $result= true; + } + + return $result; + } + + /* Sets Terminal-Server-Login value: enabled/disabled */ + function setTsLogin ($checked) + { + $flag= substr($this->ctx['CtxCfgFlags1'], 5, 1); + + if ($checked) { + $flag|= 1; + } else { + $flag&= 0xFE; + } + + $this->ctx['CtxCfgFlags1'][5]= sprintf('%1X', $flag); + } + + /* gets Broken-Connection value: disconnect/reset */ + function getBrokenConn () + { + $flags= ord(substr($this->ctx['CtxCfgFlags1'], 5, 1)); + if ($flags & 4) { + $result= "1"; + } else { + $result= "0"; + } + + return $result; + } + + /* sets Broken-Connection value: disconnect/reset */ + function setBrokenConn ($checked) + { + $flag= substr($this->ctx['CtxCfgFlags1'], 5, 1); + + if ($checked) { + $flag|= 4; + } else { + $flag&= 0xFB; + } + + $this->ctx['CtxCfgFlags1'][5]= sprintf('%1X', $flag); + } + + /* gets Reconnection value: from any client/from previous client only */ + function getReConn () + { + $flags= ord(substr($this->ctx['CtxCfgFlags1'], 5, 1)); + if ($flags & 2) { + $result= "1"; + } else { + $result= "0"; + } + + return $result; + } + + /* sets Reconnection value: from any client/from previous client only */ + function setReConn ($checked) + { + $flag= substr($this->ctx['CtxCfgFlags1'], 5, 1); + + if ($checked) { + $flag|= 2; + } else { + $flag&= 0xFD; + } + + $this->ctx['CtxCfgFlags1'][5]= sprintf('%1X', $flag); + } + + /* gets Inherit-config-from-client value: enabled/disabled */ + function getInheritMode () + { + if (substr($this->ctx['CtxCfgFlags1'], 6, 1) == "1") { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* sets Inherit-config-from-client value: enabled/disabled */ + function setInheritMode ($checked) + { + if ($checked) { + $this->ctx['CtxCfgFlags1'][6]= "1"; + } else { + $this->ctx['CtxCfgFlags1'][6]= "0"; + } + } + + /* gets shadow value (enum): 0-4 + 0: disabled + 1: input on, notify on + 2: input on, notify off + 3: input off, notify on + 4: input off, notify off + */ + function getShadow () + { + $result= substr($this->ctx['CtxCfgFlags1'], 1, 1); + return $result; + } + + /* sets shadow value */ + function setShadow ($checked, $value) + { + if ($checked) { + $this->ctx['CtxCfgFlags1'][1]= sprintf('%1X', $value); + } + } + + /* gets connect-client-drive-at-logon value: enabled/disabled */ + function getConnectClientDrives () + { + $connections= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + if ($connections & 8) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* sets connect-client-drive-at-logon value: enabled/disabled */ + function setConnectClientDrives ($checked) + { + $flag= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + if ($checked) { + $flag|= 8; + } else { + $flag&= 0xF7; + } + + $this->ctx['CtxCfgFlags1'][2]= sprintf('%1X', $flag); + } + + /* gets connect-client-printers-at-logon value: enabled/disabled */ + function getConnectClientPrinters () + { + $connections= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + if ($connections & 4) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* sets connect-client-printers-at-logon value: enabled/disabled */ + function setConnectClientPrinters ($checked) + { + $flag= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + + if ($checked) { + $flag|= 4; + } else { + $flag&= 0xFB; + } + + $this->ctx['CtxCfgFlags1'][2]= sprintf('%1X', $flag); + } + + /* gets set-client-printer-to-default value: enabled/disabled */ + function getDefaultPrinter () + { + $connections= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + if ($connections & 2) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* sets set-client-printer-to-default value: enabled/disabled */ + function setDefaultPrinter ($checked) + { + $flag= hexdec(substr($this->ctx['CtxCfgFlags1'], 2, 1)); + + if ($checked) { + $flag|= 2; + } else { + $flag&= 0xFD; + } + + $this->ctx['CtxCfgFlags1'][2]= sprintf('%1X', $flag); + } + + /* SMARTY: gets the checkbox state of "Connection" */ + function getCtxMaxConnectionTimeF () + { + // Connection Time is 0 if disabled + if (isset($this->ctx['CtxMaxConnectionTime']) && ($this->ctx['CtxMaxConnectionTime'] != 0)) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* SMARTY: sets the checkbox "Connection" to unchecked */ + function setCtxMaxConnectionTimeF ($checked) + { + if ($checked) { + unset ($this->ctx['CtxMaxConnectionTime']); + } + } + + /* SMARTY: gets the checkbox state of "Disconnection" */ + function getCtxMaxDisconnectionTimeF () + { + // Connection Time is 0 if disabled + if (isset($this->ctx['CtxMaxDisconnectionTime']) && ($this->ctx['CtxMaxDisconnectionTime'] != 0)) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* SMARTY: sets the checkbox "Disconnection" to unchecked */ + function setCtxMaxDisconnectionTimeF ($checked) + { + if ($checked) { + unset ($this->ctx['CtxMaxDisconnectionTime']); + } + } + + /* SMARTY: gets the checkbox state of "Idle" */ + function getCtxMaxIdleTimeF () + { + // Connection Time is 0 if disabled + if (isset($this->ctx['CtxMaxIdleTime']) && ($this->ctx['CtxMaxIdleTime'] != 0)) { + $result= true; + } else { + $result= false; + } + + return $result; + } + + /* SMARTY: sets the checkbox "Idle" to unchecked */ + function setCtxMaxIdleTimeF ($checked) + { + if ($checked) { + unset ($this->ctx['CtxMaxIdleTime']); + } + } + +} + +?> diff --git a/include/class_sieve.inc b/include/class_sieve.inc new file mode 100644 index 000000000..a2b62a379 --- /dev/null +++ b/include/class_sieve.inc @@ -0,0 +1,514 @@ + + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + */ + +// TODO before next release: remove ::status() and dependencies + + +define ("F_NO", 0); +define ("F_OK", 1); +define ("F_DATA", 2); +define ("F_HEAD", 3); + +define ("EC_NOT_LOGGED_IN", 0); +define ("EC_QUOTA", 10); +define ("EC_NOSCRIPTS", 20); +define ("EC_UNKNOWN", 255); +/* + +SIEVE-PHP.LIB VERSION 0.0.8 + +(C) 2001 Dan Ellis. + +PLEASE READ THE README FILE FOR MORE INFORMATION. + +Basically, this is the first re-release. Things are much better than before. + +Notes: +This program/libary has bugs. + . This was quickly hacked out, so please let me know what is wrong and if you feel ambitious submit + a patch :). + +Todo: + . Provide better error diagnostics. (mostly done with ver 0.0.5) + . Allow other auth mechanisms besides plain (in progress) + . Have timing mechanism when port problems arise. (not done yet) + . Maybe add the NOOP function. (not done yet) + . Other top secret stuff.... (some done, believe me?) + +Dan Ellis (danellis@rushmore.com) + +This program is released under the GNU Public License. + +You should have received a copy of the GNU Public + License along with this package; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +See CHANGES for updates since last release + +Contributers of patches: + Atif Ghaffar + Andrew Sterling Hanenkamp +*/ + + +class sieve +{ + var $host; + var $port; + var $user; + var $pass; + var $auth_types; /* a comma seperated list of allowed auth types, in order of preference */ + var $auth_in_use; /* type of authentication attempted */ + + var $line; + var $fp; + var $retval; + var $tmpfile; + var $fh; + var $len; + var $script; + + var $loggedin; + var $capabilities; + var $error; + var $error_raw; + var $responses; + + //maybe we should add an errorlvl that the user will pass to new sieve = sieve(,,,,E_WARN) + //so we can decide how to handle certain errors?!? + + //also add a connection type, like PLAIN, MD5, etc... + + + function get_response() + { + if($this->loggedin == false or feof($this->fp)){ + $this->error = EC_NOT_LOGGED_IN; + $this->error_raw = "You are not logged in."; + return false; + } + + unset($this->response); + unset($this->error); + unset($this->error_raw); + + $this->line=fgets($this->fp,1024); + $this->token = split(" ", $this->line, 2); + + if($this->token[0] == "NO"){ + /* we need to try and extract the error code from here. There are two possibilites: one, that it will take the form of: + NO ("yyyyy") "zzzzzzz" or, two, NO {yyyyy} "zzzzzzzzzzz" */ + $this->x = 0; + list($this->ltoken, $this->mtoken, $this->rtoken) = split(" ", $this->line." ", 3); + if($this->mtoken[0] == "{"){ + while($this->mtoken[$this->x] != "}" or $this->err_len < 1){ + $this->err_len = substr($this->mtoken, 1, $this->x); + $this->x++; + } + //print "
Trying to receive $this->err_len bytes for result
"; + $this->line = fgets($this->fp,$this->err_len); + $this->error_raw[]=substr($this->line, 0, strlen($this->line) -2); //we want to be nice and strip crlf's + $this->err_recv = strlen($this->line); + + while($this->err_recv < $this->err_len){ + //print "
Trying to receive ".($this->err_len-$this->err_recv)." bytes for result
"; + $this->line = fgets($this->fp, ($this->err_len-$this->err_recv)); + $this->error_raw[]=substr($this->line, 0, strlen($this->line) -2); //we want to be nice and strip crlf's + $this->err_recv += strlen($this->line); + } /* end while */ + $this->line = fgets($this->fp, 1024); //we need to grab the last crlf, i think. this may be a bug... + $this->error=EC_UNKNOWN; + + } /* end if */ + elseif($this->mtoken[0] == "("){ + switch($this->mtoken){ + case "(\"QUOTA\")": + $this->error = EC_QUOTA; + $this->error_raw=$this->rtoken; + break; + default: + $this->error = EC_UNKNOWN; + $this->error_raw=$this->rtoken; + break; + } /* end switch */ + } /* end elseif */ + else{ + $this->error = EC_UNKNOWN; + $this->error_raw = $this->line; + } + return false; + + } /* end if */ + elseif(substr($this->token[0],0,-2) == "OK"){ + return true; + } /* end elseif */ + elseif($this->token[0][0] == "{"){ + + /* Unable wild assumption: that the only function that gets here is the get_script(), doesn't really matter though */ + + /* the first line is the len field {xx}, which we don't care about at this point */ + $this->line = fgets($this->fp,1024); + while(substr($this->line,0,2) != "OK" and substr($this->line,0,2) != "NO"){ + $this->response[]=$this->line; + $this->line = fgets($this->fp, 1024); + } + if(substr($this->line,0,2) == "OK") + return true; + else + return false; + } /* end elseif */ + elseif($this->token[0][0] == "\""){ + + /* I'm going under the _assumption_ that the only function that will get here is the listscripts(). + I could very well be mistaken here, if I am, this part needs some rework */ + + $this->found_script=false; + + while(substr($this->line,0,2) != "OK" and substr($this->line,0,2) != "NO"){ + $this->found_script=true; + list($this->ltoken, $this->rtoken) = explode(" ", $this->line." ",2); + //hmmm, a bug in php, if there is no space on explode line, a warning is generated... + + if(strcmp(rtrim($this->rtoken), "ACTIVE")==0){ + $this->response["ACTIVE"] = substr(rtrim($this->ltoken),1,-1); + } + else + $this->response[] = substr(rtrim($this->ltoken),1,-1); + $this->line = fgets($this->fp, 1024); + } /* end while */ + + return true; + + } /* end elseif */ + else{ + $this->error = EC_UNKNOWN; + $this->error_raw = $this->line; + print "UNKNOWN ERROR (Please report this line to danellis@rushmore.com to include in future releases): $this->line
"; + return false; + } /* end else */ + } /* end get_response() */ + + function sieve($host, $port, $user, $pass, $auth="", $auth_types="PLAIN DIGEST-MD5") + { + $this->host=$host; + $this->port=$port; + $this->user=$user; + $this->pass=$pass; + if(!strcmp($auth, "")) /* If there is no auth user, we deem the user itself to be the auth'd user */ + $this->auth = $this->user; + else + $this->auth = $auth; + $this->auth_types=$auth_types; /* Allowed authentication types */ + $this->fp=0; + $this->line=""; + $this->retval=""; + $this->tmpfile=""; + $this->fh=0; + $this->len=0; + $this->capabilities=""; + $this->loggedin=false; + $this->error= ""; + $this->error_raw=""; + } + + function parse_for_quotes($string) + { + /* This function tokenizes a line of input by quote marks and returns them as an array */ + + $start = -1; + $index = 0; + + for($ptr = 0; $ptr < strlen($string); $ptr++){ + if($string[$ptr] == '"' and $string[$ptr] != '\\'){ + if($start == -1){ + $start = $ptr; + } /* end if */ + else{ + $token[$index++] = substr($string, $start + 1, $ptr - $start - 1); + $found = true; + $start = -1; + } /* end else */ + + } /* end if */ + + } /* end for */ + + if(isset($token)) + return $token; + else + return false; + } /* end function */ + + function status($string) + { + //this should probably be replaced by a smarter parser. + + /* Need to remove this and all dependencies from the class */ + + switch (substr($string, 0,2)){ + case "NO": + return F_NO; //there should be some function to extract the error code from this line + //NO ("quota") "You are oly allowed x number of scripts" + break; + case "OK": + return F_OK; + break; + default: + switch ($string[0]){ + case "{": + //do parse here for {}'s maybe modify parse_for_quotes to handle any parse delimiter? + return F_HEAD; + break; + default: + return F_DATA; + break; + } /* end switch */ + } /* end switch */ + } /* end status() */ + + function sieve_login() + { + + $this->fp=fsockopen($this->host,$this->port); + if($this->fp == false) + return false; + + $this->line=fgets($this->fp,1024); + + //Hack for older versions of Sieve Server. They do not respond with the Cyrus v2. standard + //response. They repsond as follows: "Cyrus timsieved v1.0.0" "SASL={PLAIN,........}" + //So, if we see IMLEMENTATION in the first line, then we are done. + + if(ereg("IMPLEMENTATION",$this->line)) + { + //we're on the Cyrus V2 sieve server + while(sieve::status($this->line) == F_DATA){ + + $this->item = sieve::parse_for_quotes($this->line); + + if(strcmp($this->item[0], "IMPLEMENTATION") == 0) + $this->capabilities["implementation"] = $this->item[1]; + + elseif(strcmp($this->item[0], "SIEVE") == 0 or strcmp($this->item[0], "SASL") == 0){ + + if(strcmp($this->item[0], "SIEVE") == 0) + $this->cap_type="modules"; + else + $this->cap_type="auth"; + + $this->modules = split(" ", $this->item[1]); + if(is_array($this->modules)){ + foreach($this->modules as $this->module) + $this->capabilities[$this->cap_type][$this->module]=true; + } /* end if */ + elseif(is_string($this->modules)) + $this->capabilites[$this->cap_type][$this->modules]=true; + } + else{ + $this->capabilities["unknown"][]=$this->line; + } + $this->line=fgets($this->fp,1024); + + }// end while + } + else + { + //we're on the older Cyrus V1. server + //this version does not support module reporting. We only have auth types. + $this->cap_type="auth"; + + //break apart at the "Cyrus timsieve...." "SASL={......}" + $this->item = sieve::parse_for_quotes($this->line); + + $this->capabilities["implementation"] = $this->item[0]; + + //we should have "SASL={..........}" now. Break out the {xx,yyy,zzzz} + $this->modules = substr($this->item[1], strpos($this->item[1], "{"),strlen($this->item[1])-1); + + //then split again at the ", " stuff. + $this->modules = split($this->modules, ", "); + + //fill up our $this->modules property + if(is_array($this->modules)){ + foreach($this->modules as $this->module) + $this->capabilities[$this->cap_type][$this->module]=true; + } /* end if */ + elseif(is_string($this->modules)) + $this->capabilites[$this->cap_type][$this->module]=true; + } + + + + + if(sieve::status($this->line) == F_NO){ //here we should do some returning of error codes? + $this->error=EC_UNKNOWN; + $this->error_raw = "Server not allowing connections."; + return false; + } + + /* decision login to decide what type of authentication to use... */ + + /* Loop through each allowed authentication type and see if the server allows the type */ + foreach(split(" ",$this->auth_types) as $auth_type) + { + if ($this->capabilities["auth"][$auth_type]) + { + /* We found an auth type that is allowed. */ + $this->auth_in_use = $auth_type; + break; + } + } + + /* Fill error message if no auth types are present */ + if (!isset($this->capabilities["auth"])){ + $this->error=EC_UNKNOWN; + $this->error_raw = "No authentication methods found - please check your sieve setup for missing sasl modules"; + return false; + } + + /* call our authentication program */ + return sieve::authenticate(); + + } + + function sieve_logout() + { + if($this->loggedin==false) + return false; + + fputs($this->fp,"LOGOUT\r\n"); + fclose($this->fp); + $this->loggedin=false; + return true; + } + + function sieve_sendscript($scriptname, $script) + { + if($this->loggedin==false) + return false; + $this->script=stripslashes($script); + $len=strlen($this->script); + fputs($this->fp, "PUTSCRIPT \"$scriptname\" \{$len+}\r\n"); + fputs($this->fp, "$this->script\r\n"); + + return sieve::get_response(); + + } + + //it appears the timsieved does not honor the NUMBER type. see lex.c in timsieved src. + //don't expect this function to work yet. I might have messed something up here, too. + function sieve_havespace($scriptname, $scriptsize) + { + if($this->loggedin==false) + return false; + fputs($this->fp, "HAVESPACE \"$scriptname\" $scriptsize\r\n"); + return sieve::get_response(); + + } + + function sieve_setactivescript($scriptname) + { + if($this->loggedin==false) + return false; + + fputs($this->fp, "SETACTIVE \"$scriptname\"\r\n"); + return sieve::get_response(); + + } + + function sieve_getscript($scriptname) + { + unset($this->script); + if($this->loggedin==false) + return false; + + fputs($this->fp, "GETSCRIPT \"$scriptname\"\r\n"); + return sieve::get_response(); + + } + + + function sieve_deletescript($scriptname) + { + if($this->loggedin==false) + return false; + + fputs($this->fp, "DELETESCRIPT \"$scriptname\"\r\n"); + + return sieve::get_response(); + } + + + function sieve_listscripts() + { + fputs($this->fp, "LISTSCRIPTS\r\n"); + sieve::get_response(); //should always return true, even if there are no scripts... + if(isset($this->found_script) and $this->found_script) + return true; + else{ + $this->error=EC_NOSCRIPTS; //sieve::getresponse has no way of telling wether a script was found... + $this->error_raw="No scripts found for this account."; + return false; + } + } + + function sieve_alive() + { + if(!isset($this->fp) or $this->fp==0){ + $this->error = EC_NOT_LOGGED_IN; + return false; + } + elseif(feof($this->fp)){ + $this->error = EC_NOT_LOGGED_IN; + return false; + } + else + return true; + } + + function authenticate() + { + + switch ($this->auth_in_use) { + + case "PLAIN": + $auth=base64_encode("$this->user\0$this->auth\0$this->pass"); + + $this->len=strlen($auth); + fputs($this->fp, "AUTHENTICATE \"PLAIN\" \{$this->len+}\r\n"); + fputs($this->fp, "$auth\r\n"); + + $this->line=fgets($this->fp,1024); + while(sieve::status($this->line) == F_DATA) + $this->line=fgets($this->fp,1024); + + if(sieve::status($this->line) == F_NO) + return false; + $this->loggedin=true; + return true; + break; + + default: + return false; + break; + + }//end switch + + + }//end authenticate() + + +} + + + +?> diff --git a/include/class_tabs.inc b/include/class_tabs.inc new file mode 100644 index 000000000..f94d98501 --- /dev/null +++ b/include/class_tabs.inc @@ -0,0 +1,243 @@ +dn= $dn; + $this->config= $config; + + foreach ($data as $tab){ + $this->by_name[$tab['CLASS']]= $tab['NAME']; + $this->by_object[$tab['CLASS']]= new $tab['CLASS']($this->config, $this->dn); + $this->by_object[$tab['CLASS']]->parent= &$this; + + /* Initialize current */ + if ($this->current == ""){ + $this->current= $tab['CLASS']; + } + } + + } + + function execute() + { + /* Rotate current to last */ + $this->last= $this->current; + + /* Look for pressed tab button */ + foreach ($this->by_object as $class => $obj){ + if (isset($_POST[$class]) || (isset($_POST['arg']) && $_POST['arg'] == "$class")){ + $this->current= $class; + break; + } + } + + /* Save last tab object */ + if ($this->last == $this->current){ + $this->save_object(TRUE); + } else { + $this->save_object(FALSE); + } + + /* Build tab line */ + $display= $this->gen_tabs(); + + /* Show object */ + $display.= "\n"; + $display.= "
\n"; + + $obj= $this->by_object[$this->current]; + $display.= $obj->execute (); + $this->by_object[$this->current]= $obj; + + /* Footer for tabbed dialog */ + $display.= "
"; + return ($display); + } + + function save_object($save_current= FALSE) + { + /* Save last tab */ + if ($this->last != ""){ + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + $this->last, "Saving"); + + $obj= $this->by_object[$this->last]; + $obj->save_object (); + $this->by_object[$this->last]= $obj; + } + + /* Skip if curent and last are the same object */ + if ($this->last == $this->current){ + return; + } + + $obj= $this->by_object[$this->current]; + $this->disabled= $obj->parent->disabled; + + if ($save_current){ + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + $this->current, "Saving (current)"); + + $obj->save_object (); + $this->by_object[$this->current]= $obj; + } + + } + + function gen_tabs() + { + $display= ""; + $display.= ""; + $index= 0; + $style= array("tab_left", "tab_active", "tab_near_active", "tab_right"); + foreach ($this->by_name as $class => $name){ + + /* Activate right tabs with style "tab_right" + Activate near current with style "tab_near_active" */ + if ($index == 2 || $index == 1){ + $index++; + } + + /* Activate current tab with style "tab_active " */ + if ($class == $this->current){ + $index++; + } + + /* Paint tab */ + $display.= "
"; + if ($_SESSION['js']==FALSE){ + $display.= "
"; + + return($display); + } + + + function set_acl($acl) + { + /* Set local acl */ + $this->acl= $acl; + + /* Setup for all plugins */ + foreach ($this->by_object as $key => $obj){ + $sacl= get_module_permission($acl, "$key", $this->dn); + $obj->acl= $sacl; + $this->by_object[$key]= $obj; + } + } + + function delete() + { + /* Delete for all plugins */ + foreach (array_reverse($this->by_object) as $key => $obj){ + $obj->remove_from_parent(); + } + } + + function password_change_needed() + { + /* Ask all plugins for needed password changes */ + foreach ($this->by_object as $key => $obj){ + if ($obj->password_change_needed()){ + return TRUE; + } + } + + return FALSE; + } + + function check($ignore_account= FALSE) + { + $this->save_object(TRUE); + $messages= array(); + + /* Check all plugins */ + foreach ($this->by_object as $key => $obj){ + if ($obj->is_account || $ignore_account || $obj->ignore_account){ + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + $key, "Checking"); + + $messages= $obj->check(); + if (count($messages)){ + $this->current= $key; + break; + } + } + } + + return ($messages); + } + + function save($ignore_account= FALSE) + { + /* Save all plugins */ + foreach ($this->by_object as $key => $obj){ + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + $key, "Saving"); + + $obj->dn= $this->dn; + + if ($obj->is_account || $ignore_account || $obj->ignore_account){ + if ($obj->save() == 1){ + return (1); + } + } else { + $obj->remove_from_parent(); + } + } + return (0); + } + + function adapt_from_template($dn) + { + foreach ($this->by_object as $key => $obj){ + @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, + $key, "Adapting"); + $obj->parent= &$this; + $obj->adapt_from_template($dn); + $this->by_object[$key]= $obj; + } + } + +} + +?> diff --git a/include/class_userinfo.inc b/include/class_userinfo.inc new file mode 100644 index 000000000..337c398a7 --- /dev/null +++ b/include/class_userinfo.inc @@ -0,0 +1,72 @@ +config= $config; + $ldap= $this->config->get_ldap_link(); + $ldap->cat($userdn); + $attrs= $ldap->fetch(); + + if (isset($attrs['givenName'][0]) && isset($attrs['sn'][0])){ + $this->cn= $attrs['givenName'][0]." ".$attrs['sn'][0]; + } else { + $this->cn= $attrs['uid'][0]; + } + + $this->dn= $userdn; + $this->ip= $_SERVER['REMOTE_ADDR']; + } + + + function loadACL() + { + $ldap= $this->config->get_ldap_link(); + + /* Load ACL's from all groups we're in */ + $this->subtreeACL= array(); + $ldap->cd($this->config->current['BASE']); + $ldap->search("(&(objectClass=posixGroup)(objectClass=gosaObject)". + "(|(memberUid=$this->username)(cn=$this->username)))"); + + while($attrs = $ldap->fetch()){ + $base= preg_replace('/^[^,]+,ou=[^,]+,/i', "",$ldap->getDN()); + $base= preg_replace("/[ ]*,[ ]*/", ",", $base); + + for ($i= 0; $i<$attrs["gosaSubtreeACL"]["count"]; $i++){ + $this->subtreeACL[$base][]= $attrs["gosaSubtreeACL"][$i]; + } + } + } + +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/debuglib.inc b/include/debuglib.inc new file mode 100644 index 000000000..9fd5d8bcd --- /dev/null +++ b/include/debuglib.inc @@ -0,0 +1,418 @@ + +** Filename......: debuglib.php(s) +** Last changed..: 16. July 2003 +** License.......: Free to use. Postcardware ;) +** +************************************************* +** +** Functions in this library: +** +** print_a( array array [,int mode] ) +** prints arrays in a readable, understandable form. +** if mode is defined the function returns the output instead of +** printing it to the browser +** +** +** show_vars([int mode]) +** use this function on the bottom of your script to see all +** superglobals and global variables in your script in a nice +** formated way +** +** show_vars() without parameter shows $_GET, $_POST, $_SESSION, +** $_FILES and all global variables you've defined in your script +** +** show_vars(1) shows $_SERVER and $_ENV in addition +** +** +** +** print_result( result_handle ) +** prints a mysql_result set returned by mysql_query() as a table +** this function is work in progress! use at your own risk +** +** +** +** +** Happy debugging and feel free to email me your comments. +** +** +** +** History: (starting with version 0.5.3 at 2003-02-24) +** +** - added tooltips to the td's showing the type of keys and values (thanks Itomic) +** 2003-07-16 +** - pre() function now trims trailing tabs +************************************************/ + + +# This file must be the first include on your page. + +/* used for tracking of generation-time */ +{ + $MICROTIME_START = microtime(); + @$GLOBALS_initial_count = count($GLOBALS); +} + +/************************************************ +** print_a class and helper function +** prints out an array in a more readable way +** than print_r() +** +** based on the print_a() function from +** Stephan Pirson (Saibot) +************************************************/ + +class Print_a_class { + + # this can be changed to FALSE if you don't like the fancy string formatting + var $look_for_leading_tabs = TRUE; + + var $output; + var $iterations; + var $key_bg_color = '1E32C8'; + var $value_bg_color = 'DDDDEE'; + var $fontsize = '8pt'; + var $keyalign = 'center'; + var $fontfamily = 'Verdana'; + var $export_flag; + var $show_object_vars; + var $export_dumper_path = 'http://tools.www.mdc.xmc.de/print_a_dumper/print_a_dumper.php'; + # i'm still working on the dumper! don't use it now + # put the next line into the print_a_dumper.php file (optional) + # print htmlspecialchars( stripslashes ( $_POST['array'] ) ); + var $export_hash; + + function Print_a_class() { + $this->export_hash = uniqid(''); + } + + # recursive function! + function print_a($array, $iteration = FALSE, $key_bg_color = FALSE) { + $key_bg_color or $key_bg_color = $this->key_bg_color; + + # if print_a() was called with a fourth parameter (1 or 2) + # and you click on the table a window opens with only the output of print_a() in it + # 1 = serialized array + # 2 = normal print_a() display + + /* put the following code on the page defined with $export_dumper_path; + --->%---- snip --->%---- + + if($_GET['mode'] == 1) { + print htmlspecialchars( stripslashes ( $_POST['array'] ) ); + } elseif($_GET['mode'] == 2) { + print_a(unserialize( stripslashes($_POST['array'])) ); + } + + ---%<---- snip ---%<---- + */ + + if( !$iteration && isset($this->export_flag) ) { + $this->output .= '
'; + } + + # lighten up the background color for the key td's =) + if( $iteration ) { + for($i=0; $i<6; $i+=2) { + $c = substr( $key_bg_color, $i, 2 ); + $c = hexdec( $c ); + ( $c += 15 ) > 255 and $c = 255; + isset($tmp_key_bg_color) or $tmp_key_bg_color = ''; + $tmp_key_bg_color .= sprintf( "%02X", $c ); + } + $key_bg_color = $tmp_key_bg_color; + } + + # build a single table ... may be nested + $this->output .= 'export_flag ? 'onClick="document.getElementById(\'pa_form_'.$this->export_hash.'\').submit();" )' : '' ).'>'; + foreach( $array as $key => $value ) { + + $value_style = 'color:black;'; + $key_style = 'color:white;'; + + $type = gettype( $value ); + # print $type.'
'; + + # change the color and format of the value + switch( $type ) { + case 'array': + break; + + case 'object': + $key_style = 'color:#FF9B2F;'; + break; + + case 'integer': + $value_style = 'color:green;'; + break; + + case 'double': + $value_style = 'color:red;'; + break; + + case 'bool': + $value_style = 'color:blue;'; + break; + + case 'resource': + $value_style = 'color:darkblue;'; + break; + + case 'string': + if( $this->look_for_leading_tabs && preg_match('/^\t/m', $value) ) { + $search = array('/\t/', "/\n/"); + $replace = array('   ','
'); + $value = preg_replace( $search, $replace, htmlspecialchars( $value ) ); + $value_style = 'color:black;border:1px gray dotted;'; + } else { + $value_style = 'color:black;'; + $value = nl2br( htmlspecialchars( $value ) ); + } + break; + } + + $this->output .= ''; + $this->output .= ''; + $this->output .= ''; + $this->output .= ''; + } + $this->output .= '
'; + $this->output .= $key; + $this->output .= ''; + + + # value output + if($type == 'array') { + $this->print_a( $value, TRUE, $key_bg_color ); + } elseif($type == 'object') { + if( $this->show_object_vars ) { + $this->print_a( get_object_vars( $value ), TRUE, $key_bg_color ); + } else { + $this->output .= '
OBJECT
'; + } + } else { + $this->output .= '
'.$value.'
'; + } + + $this->output .= '
'; + } +} + +# helper function.. calls print_a() inside the print_a_class +function print_a( $array, $return_mode = FALSE, $show_object_vars = FALSE, $export_flag = FALSE ) { + $e= error_reporting (0); + if( is_array( $array ) or is_object( $array ) ) { + $pa = new Print_a_class; + $show_object_vars and $pa->show_object_vars = TRUE; + $export_flag and $pa->export_flag = $export_flag; + + $pa->print_a( $array ); + + # $output = $pa->output; unset($pa); + $output = &$pa->output; + } else { + $output = 'print_a( '.gettype( $array ).' )'; + } + + error_reporting ($e); + if($return_mode) { + return $output; + } else { + print $output; + return TRUE; + } +} + + +// shows mysql-result as a table.. # not ready yet :( +function print_result($RESULT) { + + if(!$RESULT) return; + + $fieldcount = mysql_num_fields($RESULT); + + for($i=0; $i<$fieldcount; $i++) { + $tables[mysql_field_table($RESULT, $i)]++; + } + + print ' + + + '; + + print ''; + + print ''; + foreach($tables as $tableName => $tableCount) { + $col == '0054A6' ? $col = '003471' : $col = '0054A6'; + print ''; + } + print ''; + + print ''; + for($i=0;$i < mysql_num_fields($RESULT);$i++) { + $FIELD = mysql_field_name($RESULT, $i); + $col == '0054A6' ? $col = '003471' : $col = '0054A6'; + print ''; + } + print ''; + + mysql_data_seek($RESULT, 0); + + while($DB_ROW = mysql_fetch_array($RESULT, MYSQL_NUM)) { + $pointer++; + if($toggle) { + $col1 = "E6E6E6"; + $col2 = "DADADA"; + } else { + $col1 = "E1F0FF"; + $col2 = "DAE8F7"; + } + $toggle = !$toggle; + print ''; + foreach($DB_ROW as $value) { + $col == $col1 ? $col = $col2 : $col = $col1; + print ''; + } + print ''; + } + print '
'.$tableName.'
'.$FIELD.'
'.nl2br($value).'
'; + mysql_data_seek($RESULT, 0); +} + +function _script_globals() { + global $GLOBALS_initial_count; + + $varcount = 0; + + foreach($GLOBALS as $GLOBALS_current_key => $GLOBALS_current_value) { + if(++$varcount > $GLOBALS_initial_count) { + /* die wollen wir nicht! */ + if ($GLOBALS_current_key != 'HTTP_SESSION_VARS' && $GLOBALS_current_key != '_SESSION') { + $script_GLOBALS[$GLOBALS_current_key] = $GLOBALS_current_value; + } + } + } + + unset($script_GLOBALS['GLOBALS_initial_count']); + return $script_GLOBALS; +} + +function show_runtime() { + $MICROTIME_END = microtime(); + $MICROTIME_START = explode(' ', $GLOBALS['MICROTIME_START']); + $MICROTIME_END = explode(' ', $MICROTIME_END); + $GENERATIONSEC = $MICROTIME_END[1] - $MICROTIME_START[1]; + $GENERATIONMSEC = $MICROTIME_END[0] - $MICROTIME_START[0]; + $GENERATIONTIME = substr($GENERATIONSEC + $GENERATIONMSEC, 0, 8); + + return '(runtime: '.$GENERATIONTIME.' sec)'; +} + + +###################### +# function shows all superglobals and script defined global variables +# show_vars() without the first parameter shows all superglobals except $_ENV and $_SERVER +# show_vars(1) shows all +# show_vars(,1) shows object properties in addition +# +function show_vars($show_all_vars = FALSE, $show_object_vars = FALSE) { + if(isset($GLOBALS['no_vars'])) return; + + $script_globals = _script_globals(); + print ' + + '; + + print '
+
+ DEBUG '.show_runtime().' + '; + + $vars_arr['script_globals'] = array('global script variables', '#7ACCC8'); + $vars_arr['_GET'] = array('$_GET', '#7DA7D9'); + $vars_arr['_POST'] = array('$_POST', '#F49AC1'); + $vars_arr['_FILES'] = array('$_POST FILES', '#82CA9C'); + $vars_arr['_SESSION'] = array('$_SESSION', '#FCDB26'); + $vars_arr['_COOKIE'] = array('$_COOKIE', '#A67C52'); + + if($show_all_vars) { + $vars_arr['_SERVER'] = array('SERVER', '#A186BE'); + $vars_arr['_ENV'] = array('ENV', '#7ACCC8'); + } + + foreach($vars_arr as $vars_name => $vars_data) { + if($vars_name != 'script_globals') global $$vars_name; + if($$vars_name) { + print '
'.$vars_data[0].'
'; + print_a($$vars_name, FALSE, $show_object_vars, FALSE ); + print '
'; + } + } + print '
'; +} + + +###################### +# function prints sql strings +# +function pre($sql_string, $simple_mode = FALSE) { + + if(!$simple_mode) { + # erste leere Zeile im SQL löschen + $sql_string = preg_replace('/\^s+/m','', $sql_string); + # letze leere Zeile im SQL löschen + $sql_string = preg_replace('/\s+$/m','', $sql_string); + + # kleinste Anzahl von führenden TABS zählen + preg_match_all('/^\t+/m', $sql_string, $matches); + $minTabCount = strlen(min($matches[0])); + + # und entfernen + $sql_string = preg_replace('/^\t{'.$minTabCount.'}/m', '', $sql_string); + } + + print '
'.$sql_string.'
'; +} +?> diff --git a/include/functions.inc b/include/functions.inc new file mode 100644 index 000000000..549362443 --- /dev/null +++ b/include/functions.inc @@ -0,0 +1,1499 @@ + "ae", + "ö" => "oe", + "ü" => "ue", + "Ä" => "Ae", + "Ö" => "Oe", + "Ü" => "Ue", + "ß" => "ss", + "á" => "a", + "é" => "e", + "í" => "i", + "ó" => "o", + "ú" => "u", + "Á" => "A", + "É" => "E", + "Í" => "I", + "Ó" => "O", + "Ú" => "U", + "ñ" => "ny", + "Ñ" => "Ny" ); + + +/* Function to include all class_ files starting at a + given directory base */ +function get_dir_list($folder= ".") +{ + $currdir=getcwd(); + if ($folder){ + chdir("$folder"); + } + + $dh = opendir("."); + while(false !== ($file = readdir($dh))){ + + /* Recurse through all "common" directories */ + if(is_dir($file) && $file!="." && $file!=".." && $file!="CVS"){ + get_dir_list($file); + continue; + } + + /* Include existing class_ files */ + if (!is_dir($file) && preg_match("/^class_.*\.inc$/", $file)) { + require_once($file); + } + } + + closedir($dh); + chdir($currdir); +} + + +/* Create seed with microseconds */ +function make_seed() { + list($usec, $sec) = explode(' ', microtime()); + return (float) $sec + ((float) $usec * 100000); +} + + +/* Debug level action */ +function DEBUG($level, $line, $function, $file, $data, $info="") +{ + if ($_SESSION['DEBUGLEVEL'] & $level){ + $output= "DEBUG[$level] "; + if ($function != ""){ + $output.= "($file:$function():$line) - $info: "; + } else { + $output.= "($file:$line) - $info: "; + } + echo $output; + if (is_array($data)){ + print_a($data); + } else { + echo "'$data'"; + } + echo "
"; + } +} + + +/* Simple function to get browser language and convert it to + xx_XY needed by locales. Ignores sublanguages and weights. */ +function get_browser_language() +{ + global $BASE_DIR; + + /* Get list of languages */ + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){ + $lang= preg_replace("/\s+/", "", $_SERVER['HTTP_ACCEPT_LANGUAGE']); + $languages= split (',', $lang); + $languages[]= "C"; + } else { + $languages= array("C"); + } + + /* Walk through languages and get first supported */ + foreach ($languages as $val){ + + /* Strip off weight */ + $lang= preg_replace("/;q=.*$/i", "", $val); + + /* Simplify sub language handling */ + $lang= preg_replace("/-.*$/", "", $lang); + + /* Cancel loop if available in GOsa, or the last + entry has been reached */ + if (is_dir("$BASE_DIR/locale/$lang")){ + break; + } + } + + return (strtolower($lang)."_".strtoupper($lang)); +} + + +/* Rewrite ui object to another dn */ +function change_ui_dn($dn, $newdn) +{ + $ui= $_SESSION['ui']; + if ($ui->dn == $dn){ + $ui->dn= $newdn; + $_SESSION['ui']= $ui; + } +} + + +/* Return theme path for specified file */ +function get_template_path($filename= '', $plugin= FALSE, $path= "") +{ + global $config, $BASE_DIR; + + if (!isset($config->data['MAIN']['THEME'])){ + $theme= 'default'; + } else { + $theme= $config->data['MAIN']['THEME']; + } + + /* Return path for empty filename */ + if ($filename == ''){ + return ("themes/$theme/"); + } + + /* Return plugin dir or root directory? */ + if ($plugin){ + if ($path == ""){ + $nf= preg_replace("!^".$BASE_DIR."/!", "", $_SESSION['plugin_dir']); + } else { + $nf= preg_replace("!^".$BASE_DIR."/!", "", $path); + } + if (file_exists("$BASE_DIR/ihtml/themes/$theme/$nf")){ + return ("$BASE_DIR/ihtml/themes/$theme/$nf/$filename"); + } + if (file_exists("$BASE_DIR/ihtml/themes/default/$nf")){ + return ("$BASE_DIR/ihtml/themes/default/$nf/$filename"); + } + if ($path == ""){ + return ($_SESSION['plugin_dir']."/$filename"); + } else { + return ($path."/$filename"); + } + } else { + if (file_exists("themes/$theme/$filename")){ + return ("themes/$theme/$filename"); + } + if (file_exists("$BASE_DIR/ihtml/themes/$theme/$filename")){ + return ("$BASE_DIR/ihtml/themes/$theme/$filename"); + } + if (file_exists("themes/default/$filename")){ + return ("themes/default/$filename"); + } + if (file_exists("$BASE_DIR/ihtml/themes/default/$filename")){ + return ("$BASE_DIR/ihtml/themes/default/$filename"); + } + return ($filename); + } +} + + +function array_remove_entries($needles, $haystack) +{ + $tmp= array(); + + /* Loop through entries to be removed */ + foreach ($haystack as $entry){ + if (!in_array($entry, $needles)){ + $tmp[]= $entry; + } + } + + return ($tmp); +} + + +function gosa_log ($message) +{ + global $ui; + + /* Preset to something reasonable */ + $username= " unauthenticated"; + + /* Replace username if object is present */ + if (isset($ui)){ + if ($ui->username != ""){ + $username= "[$ui->username]"; + } else { + $username= "unknown"; + } + } + + syslog(LOG_WARNING,"GOsa$username: $message"); +} + + +function ldap_init ($server, $base, $binddn='', $pass='') +{ + global $config; + + $ldap = new LDAP ($binddn, $pass, $server, isset($config->current['RECURSIVE']) && $config->current['RECURSIVE'] == "true", + isset($config->current['TLS']) && $config->current['TLS'] == "true"); + + /* Sadly we've no proper return values here. Use the error message instead. */ + if (!preg_match("/Success/i", $ldap->error)){ + print_red(sprintf(_("Error when connecting the LDAP. Server said '%s'."), + $ldap->get_error())); + echo $_SESSION['errors']; + + /* Hard error. We'd like to use the LDAP, anyway... */ + exit; + } + + /* Preset connection base to $base and return to caller */ + $ldap->cd ($base); + return $ldap; +} + + +function ldap_login_user ($username, $password) +{ + global $config; + + /* look through the entire ldap */ + $ldap = $config->get_ldap_link(); + if (!preg_match("/Success/i", $ldap->error)){ + print_red(sprintf(_("User login failed. LDAP server said '%s'."), $ldap->get_error())); + echo $_SESSION['errors']; + exit; + } + $ldap->cd($config->current['BASE']); + $ldap->search("(&(uid=$username)(objectClass=gosaAccount))", array("uid")); + + /* get results, only a count of 1 is valid */ + switch ($ldap->count()){ + + /* user not found */ + case 0: return (NULL); + break; + + /* valid uniq user */ + case 1: + break; + + /* found more than one matching id */ + default: + print_red(_("Username / UID is not unique. Please check your LDAP database.")); + return (NULL); + } + + /* LDAP schema is not case sensitive. Perform additional check. */ + $attrs= $ldap->fetch(); + if ($attrs['uid'][0] != $username){ + return(NULL); + } + + /* got user dn, fill acl's */ + $ui= new userinfo($config, $ldap->getDN()); + $ui->username= $username; + + /* password check, bind as user with supplied password */ + $ldap->disconnect(); + $ldap= new LDAP($ui->dn, $password, $config->current['SERVER'], + isset($config->current['RECURSIVE']) && + $config->current['RECURSIVE'] == "true", + isset($config->current['TLS']) + && $config->current['TLS'] == "true"); + if (!preg_match("/Success/i", $ldap->error)){ + return (NULL); + } + + /* Username is set, load subtreeACL's now */ + $ui->loadACL(); + + return ($ui); +} + + +function add_lock ($object, $user) +{ + global $config; + + /* Just a sanity check... */ + if ($object == "" || $user == ""){ + print_red(_("Error while adding a lock. Parameters are not set correctly, please check the source!")); + return; + } + + /* Check for existing entries in lock area */ + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['CONFIG']); + $ldap->search("(&(objectClass=gosaLockEntry)(gosaUser=$user)(gosaObject=$object))", + array("gosaUser")); + if (!preg_match("/Success/i", $ldap->error)){ + print_red (sprintf(_("Can't set locking information in LDAP database. Please check the 'config' entry in gosa.conf! LDAP server says '%s'."), $ldap->get_error())); + return; + } + + /* Add lock if none present */ + if ($ldap->count() == 0){ + $attrs= array(); + $name= md5($object); + $ldap->cd("cn=$name,".$config->current['CONFIG']); + $attrs["objectClass"] = "gosaLockEntry"; + $attrs["gosaUser"] = $user; + $attrs["gosaObject"] = $object; + $attrs["cn"] = "$name"; + $ldap->add($attrs); + if (!preg_match("/Success/i", $ldap->error)){ + print_red(sprintf(_("Adding a lock failed. LDAP server says '%s'."), + $ldap->get_error())); + return; + } + } +} + + +function del_lock ($object) +{ + global $config; + + /* Sanity check */ + if ($object == ""){ + return; + } + + /* Check for existance and remove the entry */ + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['CONFIG']); + $ldap->search ("(&(objectClass=gosaLockEntry)(gosaObject=$object))", array("gosaObject")); + $attrs= $ldap->fetch(); + if ($ldap->getDN() != "" && preg_match("/Success/i", $ldap->error)){ + $ldap->rmdir ($ldap->getDN()); + + if (!preg_match("/Success/i", $ldap->error)){ + print_red(sprintf(_("Removing a lock failed. LDAP server says '%s'."), + $ldap->get_error())); + return; + } + } +} + + +function del_user_locks($userdn) +{ + global $config; + + /* Get LDAP ressources */ + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['CONFIG']); + + /* Remove all objects of this user, drop errors silently in this case. */ + $ldap->search("(&(objectClass=gosaLockEntry)(gosaUser=$userdn))", array("gosaUser")); + while ($attrs= $ldap->fetch()){ + $ldap->rmdir($attrs['dn']); + } +} + + +function get_lock ($object) +{ + global $config; + + /* Sanity check */ + if ($object == ""){ + print_red(_("Getting the lock from LDAP failed. Parameters are not sed correctly, please check the source!")); + return(""); + } + + /* Get LDAP link, check for presence of the lock entry */ + $user= ""; + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['CONFIG']); + $ldap->search("(&(objectClass=gosaLockEntry)(gosaObject=$object))", array("gosaUser")); + if (!preg_match("/Success/i", $ldap->error)){ + print_red (_("Can't get locking information in LDAP database. Please check the 'config' entry in gosa.conf!")); + return(""); + } + + /* Check for broken locking information in LDAP */ + if ($ldap->count() > 1){ + + /* Hmm. We're removing broken LDAP information here and issue a warning. */ + print_red(_("Found multiple locks for object to be locked. This should not be possible - cleaning up multiple references.")); + + /* Clean up these references now... */ + while ($attrs= $ldap->fetch()){ + $ldap->rmdir($attrs['dn']); + } + + return(""); + + } elseif ($ldap->count() == 1){ + $attrs = $ldap->fetch(); + $user= $attrs['gosaUser'][0]; + } + + return ($user); +} + + +function get_list($subtreeACL, $filter, $subsearch= TRUE, $base="", $attrs= array(), $flag= FALSE) +{ + global $config; + + /* Base the search on default base if not set */ + $ldap= $config->get_ldap_link($flag); + if ($base == ""){ + $ldap->cd ($config->current['BASE']); + } else { + $ldap->cd ($base); + } + + /* Perform ONE or SUB scope searches? */ + if ($subsearch) { + $ldap->search ($filter, $attrs); + } else { + $ldap->ls ($filter); + } + + /* Check for size limit exceeded messages for GUI feedback */ + if (preg_match("/size limit/i", $ldap->error)){ + $_SESSION['limit_exceeded']= TRUE; + } else { + $_SESSION['limit_exceeded']= FALSE; + } + + /* Crawl through reslut entries and perform the migration to the + result array */ + $result= array(); + while($attrs = $ldap->fetch()) { + $dn= preg_replace("/[ ]*,[ ]*/", ",", $ldap->getDN()); + foreach ($subtreeACL as $key => $value){ + if (preg_match("/$key/", $dn)){ + $attrs["dn"]= $dn; + $result[]= $attrs; + break; + } + } + } + + return ($result); +} + + +function check_sizelimit() +{ + /* Ignore dialog? */ + if (isset($_SESSION['size_ignore']) && $_SESSION['size_ignore']){ + return (""); + } + + /* Eventually show dialog */ + if (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded']){ + $smarty= get_smarty(); + $smarty->assign('warning', sprintf(_("The size limit of %d entries is exceed!"), + $_SESSION['size_limit'])); + $smarty->assign('limit_message', sprintf(_("Set the new size limit to %s and show me this message if the limit still exceeds"), '')); + return($smarty->fetch(get_template_path('sizelimit.tpl'))); + } + + return (""); +} + + +function print_sizelimit_warning() +{ + if (isset($_SESSION['size_limit']) && $_SESSION['size_limit'] >= 10000000 || + (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded'])){ + $config= ""; + } else { + $config= ""; + } + if (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded']){ + return ("("._("incomplete").") $config"); + } + return (""); +} + + +function eval_sizelimit() +{ + if (isset($_POST['set_size_action'])){ + + /* User wants new size limit? */ + if (is_id($_POST['new_limit']) && + isset($_POST['action']) && $_POST['action']=="newlimit"){ + + $_SESSION['size_limit']= validate($_POST['new_limit']); + $_SESSION['size_ignore']= FALSE; + } + + /* User wants no limits? */ + if (isset($_POST['action']) && $_POST['action']=="ignore"){ + $_SESSION['size_limit']= 0; + $_SESSION['size_ignore']= TRUE; + } + + /* User wants incomplete results */ + if (isset($_POST['action']) && $_POST['action']=="limited"){ + $_SESSION['size_ignore']= TRUE; + } + } + + /* Allow fallback to dialog */ + if (isset($_POST['edit_sizelimit'])){ + $_SESSION['size_ignore']= FALSE; + } +} + + +function get_permissions ($dn, $subtreeACL) +{ + global $config; + + $base= $config->current['BASE']; + $tmp= "d,".$dn; + $sacl= array(); + + /* Sort subacl's for lenght to simplify matching + for subtrees */ + foreach ($subtreeACL as $key => $value){ + $sacl[$key]= strlen($key); + } + arsort ($sacl); + reset ($sacl); + + /* Successively remove leading parts of the dn's until + it doesn't contain commas anymore */ + while (preg_match('/,/', $tmp)){ + $tmp= ltrim(strstr($tmp, ","), ","); + + /* Check for acl that may apply */ + foreach ($sacl as $key => $value){ + if (preg_match("/$key$/", $tmp)){ + return ($subtreeACL[$key]); + } + } + } + + return array(""); +} + + +function get_module_permission($acl_array, $module, $dn) +{ + global $ui; + + $final= ""; + foreach($acl_array as $acl){ + + /* Check for selfflag (!) in ACL to determine if + the user is allowed to change parts of his/her + own account */ + if (preg_match("/^!/", $acl)){ + if ($dn != "" && $dn != $ui->dn){ + + /* No match for own DN, give up on this ACL */ + continue; + + } else { + + /* Matches own DN, remove the selfflag */ + $acl= preg_replace("/^!/", "", $acl); + + } + } + + /* Remove leading garbage */ + $acl= preg_replace("/^:/", "", $acl); + + /* Discover if we've access to the submodule by comparing + all allowed submodules specified in the ACL */ + $tmp= split(",", $acl); + foreach ($tmp as $mod){ + if (preg_match("/$module#/", $mod)){ + $final= strstr($mod, "#")."#"; + continue; + } + if (preg_match("/[^#]$module$/", $mod)){ + return ("#all#"); + } + if (preg_match("/^all$/", $mod)){ + return ("#all#"); + } + } + } + + /* Return assembled ACL, or none */ + if ($final != ""){ + return (preg_replace('/##/', '#', $final)); + } + + /* Nothing matches - disable access for this object */ + return ("#none#"); +} + + +function get_userinfo() +{ + global $ui; + + return $ui; +} + + +function get_smarty() +{ + global $smarty; + + return $smarty; +} + + +function convert_department_dn($dn) +{ + $dep= ""; + + /* Build a sub-directory style list of the tree level + specified in $dn */ + foreach (split (",", $dn) as $val){ + + /* We're only interested in organizational units... */ + if (preg_match ("/ou=/", $val)){ + $dep= preg_replace("/ou=([^,]+)/", "\\1", $val)."/$dep"; + } + + /* ... and location objects */ + if (preg_match ("/l=/", $val)){ + $dep= preg_replace("/l=([^,]+)/", "\\1", $val)."/$dep"; + } + } + + /* Return and remove accidently trailing slashes */ + return rtrim($dep, "/"); +} + + +function get_ou($name) +{ + global $config; + + $ou= $config->current[$name]; + if ($ou != ""){ + if (!preg_match('/^[^=]+=[^=]+/', $ou)){ + return "ou=$ou,"; + } else { + return "$ou,"; + } + } else { + return ""; + } +} + + +function get_people_ou() +{ + return (get_ou("PEOPLE")); +} + + +function get_groups_ou() +{ + return (get_ou("GROUPS")); +} + + +function get_winstations_ou() +{ + return (get_ou("WINSTATIONS")); +} + + +function get_base_from_people($dn) +{ + global $config; + + $pattern= "/^[^,]+,".preg_quote(get_people_ou())."/"; + $base= preg_replace($pattern, '', $dn); + + /* Set to base, if we're not on a correct subtree */ + if (!isset($config->idepartments[$base])){ + $base= $config->current['BASE']; + } + + return ($base); +} + + +function get_departments($ignore_dn= "") +{ + global $config; + + /* Initialize result hash */ + $result= array(); + $result['/']= $config->current['BASE']; + + /* Get list of department objects */ + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['BASE']); + $ldap->search ("(objectClass=gosaDepartment)", array("ou")); + while ($attrs= $ldap->fetch()){ + $dn= $ldap->getDN(); + if ($dn == $ignore_dn){ + continue; + } + $result[convert_department_dn($dn)]= $dn; + } + + return ($result); +} + + +function chkacl($acl, $name) +{ + /* Look for attribute in ACL */ + if (preg_match("/#$name#/", $acl) || $acl == "#all#"){ + return (""); + } + + /* Optically disable html object for no match */ + return (" disabled "); +} + + +function is_phone_nr($nr) +{ + if ($nr == ""){ + return (TRUE); + } + + return preg_match ("/^[0-9 ()+*-]+$/", $nr); +} + + +function is_url($url) +{ + if ($url == ""){ + return (TRUE); + } + + return preg_match ("/^(http|https):\/\/((?:[a-zA-Z0-9_-]+\.?)+):?(\d*)/", $url); +} + + +function is_dn($dn) +{ + if ($dn == ""){ + return (TRUE); + } + + return preg_match ("/^[a-z0-9 _-]+$/i", $dn); +} + + +function is_uid($uid) +{ + global $config; + + if ($uid == ""){ + return (TRUE); + } + + /* STRICT adds spaces and case insenstivity to the uid check. + This is dangerous and should not be used. */ + if (isset($config->current['STRICT']) && preg_match('/^no$/i', $config->current['STRICT'])){ + return preg_match ("/^[a-z0-9 _.-]+$/i", $uid); + } else { + return preg_match ("/^[a-z0-9_-]+$/", $uid); + } +} + + +function is_id($id) +{ + if ($id == ""){ + return (FALSE); + } + + return preg_match ("/^[0-9]+$/", $id); +} + + +function is_path($path) +{ + if ($path == ""){ + return (TRUE); + } + if (!preg_match('/^[a-z0-9%\/_.+-]+$/i', $path)){ + return (FALSE); + } + + return preg_match ("/\/.+$/", $path); +} + + +function is_email($address, $template= FALSE) +{ + if ($address == ""){ + return (TRUE); + } + if ($template){ + return preg_match ("/^[._a-z0-9%-]+@[_a-z0-9-]+(\.[a-z0-9-]+)(\.[a-z0-9-]+)*$/i", + $address); + } else { + return preg_match ("/^[._a-z0-9-]+@[_a-z0-9-]+(\.[a-z0-9i-]+)(\.[a-z0-9-]+)*$/i", + $address); + } +} + + +function print_red() +{ + /* Check number of arguments */ + if (func_num_args() < 1){ + return; + } + + /* Get arguments, save string */ + $array = func_get_args(); + $string= $array[0]; + + /* Step through arguments */ + for ($i= 1; $i". + "
". + "$string". + "
\n"; + } else { + echo "Error: $string\n"; + } +} + + +function gen_locked_message($user, $dn) +{ + global $plug, $config; + + $_SESSION['dn']= $dn; + $ldap= $config->get_ldap_link(); + $ldap->cat ($user); + $attrs= $ldap->fetch(); + $uid= $attrs["uid"][0]; + + /* Prepare and show template */ + $smarty= get_smarty(); + $smarty->assign ("dn", $dn); + $smarty->assign ("message", sprintf(_("You're going to edit the LDAP entry '%s' which appears to be used by '%s'. Please contact the person in order to clarify proceedings."), $dn, "$uid")); + + return ($smarty->fetch (get_template_path('islocked.tpl'))); +} + + +function to_string ($value) +{ + /* If this is an array, generate a text blob */ + if (is_array($value)){ + $ret= ""; + foreach ($value as $line){ + $ret.= $line."
\n"; + } + return ($ret); + } else { + return ($value); + } +} + + +function get_printer_list($cups_server) +{ + global $config; + + $res= array(); + + /* Use CUPS, if we've access to it */ + if (function_exists('cups_get_dest_list')){ + $dest_list= cups_get_dest_list ($cups_server); + + foreach ($dest_list as $prt){ + $attr= cups_get_printer_attributes ($cups_server, $prt->name); + + foreach ($attr as $prt_info){ + if ($prt_info->name == "printer-info"){ + $info= $prt_info->value; + break; + } + } + $res[$prt->name]= "$info [$prt->name]"; + } + + /* CUPS is not available, try lpstat as a replacement */ + } else { + unset ($ar); + exec("lpstat -p", $ar); + foreach($ar as $val){ + list($dummy, $printer, $rest)= split(' ', $val, 3); + if (preg_match('/^[^@]+$/', $printer)){ + $res[$printer]= "$printer"; + } + } + } + + /* Merge in printers from LDAP */ + $ldap= $config->get_ldap_link(); + $ldap->cd ($config->current['BASE']); + $ldap->search('(objectClass=gotoPrinter)', array('cn')); + while ($attrs= $ldap->fetch()){ + $res[$attrs["cn"][0]]= $attrs["cn"][0]; + } + + return $res; +} + + +function sess_del ($var) +{ + /* New style */ + unset ($_SESSION[$var]); + + /* ... work around, since the first one + doesn't seem to work all the time */ + session_unregister ($var); +} + + +function show_errors($message) +{ + $complete= ""; + + /* Assemble the message array to a plain string */ + foreach ($message as $error){ + if ($complete == ""){ + $complete= $error; + } else { + $complete= "$error
$complete"; + } + } + + /* Fill ERROR variable with nice error dialog */ + print_red($complete); +} + + +function show_ldap_error($message) +{ + if (!preg_match("/Success/i", $message)){ + print_red (_("LDAP error:")." $message"); + return TRUE; + } else { + return FALSE; + } +} + + +function rewrite($s) +{ + global $REWRITE; + + foreach ($REWRITE as $key => $val){ + $s= preg_replace("/$key/", "$val", $s); + } + + return ($s); +} + + +function dn2base($dn) +{ + global $config; + + if (get_people_ou() != ""){ + $dn= preg_replace('/,'.get_people_ou().'/' , ',', $dn); + } + if (get_groups_ou() != ""){ + $dn= preg_replace('/,'.get_groups_ou().'/' , ',', $dn); + } + $base= preg_replace ('/^[^,]+,/i', '', $dn); + + return ($base); +} + + + +function check_command($cmdline) +{ + $cmd= preg_replace("/ .*$/", "", $cmdline); + + /* Check if command exists in filesystem */ + if (!file_exists($cmd)){ + return (FALSE); + } + + /* Check if command is executable */ + if (!is_executable($cmd)){ + return (FALSE); + } + + return (TRUE); +} + + +function print_header($image, $headline, $info= "") +{ + $display= "
\n"; + $display.= " \"*\" $headline\n"; + $display.= "
\n"; + + if ($info != ""){ + $display.= "
\n"; + $display.= "$info"; + $display.= "
\n"; + } else { + $display.= "
\n"; + $display.= " "; + $display.= "
\n"; + } + + return ($display); +} + + +function register_global($name, $object) +{ + $_SESSION[$name]= $object; +} + + +function is_global($name) +{ + return isset($_SESSION[$name]); +} + + +function get_global($name) +{ + return $_SESSION[$name]; +} + + +function range_selector($dcnt,$start,$range=25) +{ + + /* Entries shown left and right from the selected entry */ + $max_entries= 10; + + /* Initialize and take care that max_entries is even */ + $output=""; + if ($max_entries & 1){ + $max_entries++; + } + + /* Prevent output to start or end out of range */ + if ($start < 0 ){ + $start= 0 ; + } + if ($start >= $dcnt){ + $start= $range * (int)(($dcnt / $range) + 0.5); + } + + $numpages= (($dcnt / $range)); + if(((int)($numpages))!=($numpages)) + $numpages = (int)$numpages + 1; + $ppage= (int)(($start / $range) + 0.5); + + + /* Align selected page to +/- max_entries/2 */ + $begin= $ppage - $max_entries/2; + $end= $ppage + $max_entries/2; + + /* Adjust begin/end, so that the selected value is somewhere in + the middle and the size is max_entries if possible */ + if ($begin < 0){ + $end-= $begin + 1; + $begin= 0; + } + if ($end > $numpages) { + $end= $numpages; + } + if (($end - $begin) < $max_entries && ($end - $max_entries) > 0){ + $begin= $end - $max_entries; + } + + /* Draw decrement */ + if ($start > 0 ) { + $output.=" ". + ""; + } + + /* Draw pages */ + for ($i= $begin; $i < $end; $i++) { + if ($ppage == $i){ + $output.= " ".($i+1)." "; + } else { + $output.= " ".($i+1)." "; + } + } + + /* Draw increment */ + if($start < ($dcnt-$range)) { + $output.=" ". + ""; + } + + return($output); +} + + +function apply_filter() +{ + $apply= ""; + + $apply= '

'. + '
'. + '

'; + + return ($apply); +} + + +function back_to_main() +{ + $string= '

'; + + return ($string); +} + + +function normalize_netmask($netmask) +{ + /* Check for notation of netmask */ + if (!preg_match('/^([0-9]+\.){3}[0-9]+$/', $netmask)){ + $num= (int)($netmask); + $netmask= ""; + + for ($byte= 0; $byte<4; $byte++){ + $result=0; + + for ($i= 7; $i>=0; $i--){ + if ($num-- > 0){ + $result+= pow(2,$i); + } + } + + $netmask.= $result."."; + } + + return (preg_replace('/\.$/', '', $netmask)); + } + + return ($netmask); +} + + +function netmask_to_bits($netmask) +{ + list($nm0, $nm1, $nm2, $nm3)= split('\.', $netmask); + $res= 0; + + for ($n= 0; $n<4; $n++){ + $start= 255; + $name= "nm$n"; + + for ($i= 0; $i<8; $i++){ + if ($start == (int)($$name)){ + $res+= 8 - $i; + break; + } + $start-= pow(2,$i); + } + } + + return ($res); +} + + +function recurse($rule, $variables) +{ + $result= array(); + + if (!count($variables)){ + return array($rule); + } + + reset($variables); + $key= key($variables); + $val= current($variables); + unset ($variables[$key]); + + foreach($val as $possibility){ + $nrule= preg_replace("/\{$key\}/", $possibility, $rule); + $result= array_merge($result, recurse($nrule, $variables)); + } + + return ($result); +} + + +function expand_id($rule, $attributes) +{ + /* Check for id rule */ + if(preg_match('/^id(:|#)\d+$/',$rule)){ + return (array("\{$rule}")); + } + + /* Check for clean attribute */ + if (preg_match('/^%[a-zA-Z0-9]+$/', $rule)){ + $rule= preg_replace('/^%/', '', $rule); + $val= rewrite(preg_replace('/ /', '', strtolower($attributes[$rule]))); + return (array($val)); + } + + /* Check for attribute with parameters */ + if (preg_match('/^%[a-zA-Z0-9]+\[[0-9-]+\]$/', $rule)){ + $param= preg_replace('/^[^[]+\[([^]]+)]$/', '\\1', $rule); + $part= preg_replace('/^%/', '', preg_replace('/\[.*$/', '', $rule)); + $val= rewrite(preg_replace('/ /', '', strtolower($attributes[$part]))); + $start= preg_replace ('/-.*$/', '', $param); + $stop = preg_replace ('/^[^-]+-/', '', $param); + + /* Assemble results */ + $result= array(); + for ($i= $start; $i<= $stop; $i++){ + $result[]= substr($val, 0, $i); + } + return ($result); + } + + echo "Error in idgen string: don't know how to handle rule $rule.\n"; + return (array($rule)); +} + + +function gen_uids($rule, $attributes) +{ + global $config; + + /* Search for keys and fill the variables array with all + possible values for that key. */ + $part= ""; + $trigger= false; + $stripped= ""; + $variables= array(); + + for ($pos= 0; $pos < strlen($rule); $pos++){ + + if ($rule[$pos] == "{" ){ + $trigger= true; + $part= ""; + continue; + } + + if ($rule[$pos] == "}" ){ + $variables[$pos]= expand_id($part, $attributes); + $stripped.= "\{$pos}"; + $trigger= false; + continue; + } + + if ($trigger){ + $part.= $rule[$pos]; + } else { + $stripped.= $rule[$pos]; + } + } + + /* Recurse through all possible combinations */ + $proposed= recurse($stripped, $variables); + + /* Get list of used ID's */ + $used= array(); + $ldap= $config->get_ldap_link(); + $ldap->cd($config->current['BASE']); + $ldap->search('(uid=*)'); + + while($attrs= $ldap->fetch()){ + $used[]= $attrs['uid'][0]; + } + + /* Remove used uids and watch out for id tags */ + $ret= array(); + foreach($proposed as $uid){ + + /* Check for id tag and modify uid if needed */ + if(preg_match('/\{id:\d+}/',$uid)){ + $size= preg_replace('/^.*{id:(\d+)}.*$/', '\\1', $uid); + + for ($i= 0; $i < pow(10,$size); $i++){ + $number= sprintf("%0".$size."d", $i); + $res= preg_replace('/{id:(\d+)}/', $number, $uid); + if (!in_array($res, $used)){ + $uid= $res; + break; + } + } + } + + if(preg_match('/\{id#\d+}/',$uid)){ + $size= preg_replace('/^.*{id#(\d+)}.*$/', '\\1', $uid); + + while (true){ + mt_srand((double) microtime()*1000000); + $number= sprintf("%0".$size."d", mt_rand(0, pow(10, $size)-1)); + $res= preg_replace('/{id#(\d+)}/', $number, $uid); + if (!in_array($res, $used)){ + $uid= $res; + break; + } + } + } + + /* Don't assign used ones */ + if (!in_array($uid, $used)){ + $ret[]= $uid; + } + } + + return(array_unique($ret)); +} + + +function array_search_r($needle, $key, $haystack){ + + foreach($haystack as $index => $value){ + $match= 0; + + if (is_array($value)){ + $match= array_search_r($needle, $key, $value); + } + + if ($index==$key && !is_array($value) && preg_match("/$needle/i", $value)){ + $match=1; + } + + if ($match){ + return 1; + } + } + + return 0; +} + + +/* Sadly values like memory_limit are perpended by K, M, G, etc. + Need to convert... */ +function to_byte($value) { + $value= strtolower(trim($value)); + + if(!is_numeric(substr($value, -1))) { + + switch(substr($value, -1)) { + case 'g': + $mult= 1073741824; + break; + case 'm': + $mult= 1048576; + break; + case 'k': + $mult= 1024; + break; + } + + return ($mult * (int)substr($value, 0, -1)); + } else { + return $value; + } +} + + +function in_array_ics($value, $items) +{ + foreach ($items as $item){ + if (strtolower($item) == strtolower($value)) { + return (TRUE); + } + } + + return (FALSE); +} + + +function generate_alphabet($count= 10) +{ + $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + $alphabet= ""; + $c= 0; + + /* Fill cells with charaters */ + for ($i= 0; $i ".$ch." "; + + if ($c++ == $count){ + $alphabet.= ""; + $c= 0; + } + } + + /* Fill remaining cells */ + while ($c++ <= $count){ + $alphabet.= " "; + } + + return ($alphabet); +} + + +function validate($string) +{ + return (strip_tags(preg_replace('/\0/', '', $string))); +} + + + + + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/functions_cli.inc b/include/functions_cli.inc new file mode 100644 index 000000000..06b76211d --- /dev/null +++ b/include/functions_cli.inc @@ -0,0 +1,105 @@ +\n"; + echo "Commands:\n"; + echo "\tcreate\t\tCreates an object under 'entry dn', the content\n"; + echo "\t\t\tand type is set by the -plugin option\n"; + echo "\tdelete\t\tRemoves the either the entry given by 'entry dn',\n"; + echo "\t\t\tor removes a property set by the -plugin option\n"; + echo "\tlist\t\tLists either all objects, object types given by\n"; + echo "\t\t\tthe -plugin option or a single object given by\n"; + echo "\t\t\tthe 'entry dn'. Use -list to specify the list type\n"; + echo "\tmodify\t\tModifies the entry given by 'entry dn' using\n"; + echo "\t\t\tthe object type given by the -plugin option\n"; + echo "Options:\n"; + echo "\t--location=name\tChoose the LDAP profile to work on\n"; + echo "\t--entry-dn=\tDN to perform actions on\n"; + echo "\t--entry-id=\tID to perform actions on. This option is more fuzzy\n"; + echo "\t\t\tthan the -entry-dn one. It depends on the selected plugin\n"; + echo "\t\t\tand can be i.e. an uid in case of the user plugin or a cn\n"; + echo "\t\t\tin case of a group or department\n"; + echo "\t--list=\tSpecifys the detail of the list command. Possible\n"; + echo "\t\t\tvalues are 'summary' and 'ldif'. The list command defaults\n"; + echo "\t\t\tto 'summary'\n"; + echo "\t--modifyer=\tSet the name of the person who's performing changes\n"; + echo "\t--plugin=\tSelect plugin to work with, use 'list'\n"; + echo "\t\t\tto get a list of available plugins. Every plguin\n"; + echo "\t\t\trequires one or more attributes to be set. You can\n"; + echo "\t\t\tget the list of attributes by using '-help'\n"; +} + + +function get_plugin_list($config) +{ + $plugins= array(); + foreach($config->data['MENU'] as $plugin){ + foreach ($plugin as $value){ + if (isset($value['CLASS'])){ + if (class_exists($value['CLASS'])){ + $obj= new $value['CLASS']($config, 'new'); + if (isset($obj->cli_summary)){ + $plugins[$value['CLASS']]= $obj->cli_summary; + } else { + $plugins[$value['CLASS']]= "- no description -"; + } + } + } + } + } + foreach($config->data['TABS'] as $plugin){ + foreach ($plugin as $value){ + if (isset($value['CLASS'])){ + if (class_exists($value['CLASS'])){ + $obj= new $value['CLASS']($config, 'new'); + if (isset($obj->cli_summary)){ + $plugins[$value['CLASS']]= $obj->cli_summary; + } else { + $plugins[$value['CLASS']]= "- no description -"; + } + } + } + } + } + #ksort ($plugins); + + return ($plugins); +} + + +function show_plugin_list($config) +{ + printf ("\t%-25s%s\n", "Plugin", "Description"); + $plugins= get_plugin_list($config); + foreach ($plugins as $plugin => $description){ + printf ("\t %-25s%s\n", $plugin, $description); + } +} + + +function show_plugin_help($plugin) +{ + global $config; + + $plugins= get_plugin_list($config); + if (!class_exists($plugin)){ + echo "Plugin '$plugin' does not exist\n"; + } else { + $obj= new $plugin($config, 'new'); + if (isset($obj->cli_summary)){ + echo $obj->cli_summary."\n\n"; + } + if (isset($obj->cli_description)){ + echo $obj->cli_description."\n\n"; + } + if (isset($obj->cli_parameters)){ + print_r ($obj->cli_parameters); + } else { + echo "There's no parameter description for this plugin, sorry.\n"; + } + } + +} + +?> diff --git a/include/php_setup.inc b/include/php_setup.inc new file mode 100644 index 000000000..e74f4eebe --- /dev/null +++ b/include/php_setup.inc @@ -0,0 +1,40 @@ +template_dir = $BASE_DIR.'/ihtml/'; +$smarty->caching= false; +$smarty->php_handling= SMARTY_PHP_REMOVE; + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/scanner.inc b/include/scanner.inc new file mode 100644 index 000000000..3ebf2a102 --- /dev/null +++ b/include/scanner.inc @@ -0,0 +1,533 @@ +abaton "Abaton" "Scan 300/GS" "SCSI" +abaton "Abaton" "Scan 300/S" "SCSI" +agfafocus "AGFA" "Focus GS Scanner" "SCSI" +agfafocus "AGFA" "Focus Lineart Scanner" "SCSI" +agfafocus "AGFA" "Focus II" "SCSI" +agfafocus "AGFA" "Focus Color" "SCSI" +agfafocus "AGFA" "Focus Color Plus" "SCSI" +agfafocus "Siemens" "S9036" "SCSI" +apple "Apple" "Apple Scanner" "SCSI" +apple "Apple" "OneScanner" "SCSI" +apple "Apple" "ColorOneScanner" "SCSI" +artec "Artec/Ultima" "AT3" "SCSI" +artec "Artec/Ultima" "A6000C" "SCSI" +artec "Artec/Ultima" "A6000C PLUS" "SCSI" +artec "Artec/Ultima" "AT6" "SCSI" +artec "Artec/Ultima" "AT12" "SCSI" +artec "Artec/Ultima" "AM12S" "SCSI" +artec "BlackWidow" "BW4800SP" "SCSI" +artec "Plustek" "OpticPro 19200S" "SCSI" +artec_eplus48u "Artec" "E+ 48U" "USB" +artec_eplus48u "Tevion" "MD9693" "USB" +artec_eplus48u "Medion" "MD9693" "USB" +artec_eplus48u "Medion" "MD9705" "USB" +artec_eplus48u "Medion" "MD4394" "USB" +artec_eplus48u "Trust" "Easy Webscan 19200" "USB" +artec_eplus48u "Memorex" "Mem 48 u" "USB" +as6e "Artec/Ultima" "AS6E" "Parport" +avision "Avision" "AV100CS" "SCSI" +avision "Avision" "AV100IIICS" "SCSI" +avision "Avision" "AV100S" "SCSI" +avision "Avision" "AV240SC" "SCSI" +avision "Avision" "AV260CS" "SCSI" +avision "Avision" "AV360CS" "SCSI" +avision "Avision" "AV363CS" "SCSI" +avision "Avision" "AV420CS" "SCSI" +avision "Avision" "AV6120" "SCSI" +avision "Avision" "AV620CS" "SCSI" +avision "Avision" "AV620CS Plus" "SCSI" +avision "Avision" "AV630CS" "SCSI" +avision "Avision" "AV630CSL" "SCSI" +avision "Avision" "AV6240" "SCSI" +avision "Avision" "AV600U" "USB" +avision "Avision" "AV660S" "USB" +avision "Avision" "AV680S" "USB" +avision "Avision" "AV690U" "USB" +avision "Avision" "AV800S" "SCSI" +avision "Avision" "AV810C" "SCSI" +avision "Avision" "AV820" "SCSI" +avision "Avision" "AV820C" "SCSI" +avision "Avision" "AV820C Plus" "SCSI" +avision "Avision" "AV830C" "SCSI" +avision "Avision" "AV830C Plus" "SCSI" +avision "Avision" "AV880" "SCSI" +avision "Avision" "AV880C" "SCSI" +avision "Avision" "AV8000S" "SCSI" +avision "Avision" "AVA3" "SCSI" +avision "Hewlett-Packard" "ScanJet 5300C" "USB" +avision "Hewlett-Packard" "ScanJet 5370C" "USB" +avision "Hewlett-Packard" "ScanJet 7400c" "USB" +avision "Minolta" "FS-V1" "USB" +avision "Mitsubishi" "MCA-ADFC" "SCSI" +avision "Mitsubishi" "S1200C" "SCSI" +avision "Mitsubishi" "S600C" "SCSI" +avision "Mitsubishi" "SS600" "SCSI" +avision "Fujitsu" "ScanPartner" "SCSI" +avision "Fujitsu" "ScanPartner 10" "SCSI" +avision "Fujitsu" "ScanPartner 10C" "SCSI" +avision "Fujitsu" "ScanPartner 15C" "SCSI" +avision "Fujitsu" "ScanPartner 300C" "SCSI" +avision "Fujitsu" "ScanPartner 600C" "SCSI" +avision "Fujitsu" "ScanPartner Jr" "SCSI" +bh "Bell and Howell" "COPISCAN II 6338" "SCSI" +bh "Bell and Howell" "COPISCAN II 2135" "SCSI" +bh "Bell and Howell" "COPISCAN II 2137(A)" "SCSI" +bh "Bell and Howell" "COPISCAN II 2138A" "SCSI" +bh "Bell and Howell" "COPISCAN II 3238" "SCSI" +bh "Bell and Howell" "COPISCAN II 3338(A)" "SCSI" +canon "Canon" "CanoScan 300" "SCSI" +canon "Canon" "CanoScan 600" "SCSI" +canon "Canon" "CanoScan 620S" "SCSI" +canon "Canon" "CanoScan 2700F" "SCSI" +canon "Canon" "CanoScan 2710" "SCSI" +canon630u "Canon" "CanoScan fb630u" "USB" +canon630u "Canon" "CanoScan fb636u" "USB" +canon_pp "Canon" "CanoScan FB310P" "Parport (ECP)" +canon_pp "Canon" "CanoScan FB610P" "Parport (ECP)" +canon_pp "Canon" "CanoScan FB320P" "Parport (ECP)" +canon_pp "Canon" "CanoScan FB620P" "Parport (ECP)" +canon_pp "Canon" "CanoScan FB330P" "Parport (ECP)" +canon_pp "Canon" "CanoScan FB630P" "Parport (ECP)" +canon_pp "Canon" "CanoScan N340P" "Parport (ECP)" +canon_pp "Canon" "CanoScan N640P" "Parport (ECP)" +canon_pp "Canon" "CanoScan N640P ex" "Parport (ECP)" +coolscan "Nikon" "LS-20" "SCSI" +coolscan "Nikon" "LS-30" "SCSI" +coolscan "Nikon" "LS-2000" "SCSI" +coolscan "Nikon" "LS-1000" "SCSI" +coolscan2 "Nikon" "LS 30" "SCSI" +coolscan2 "Nikon" "LS 2000" "SCSI" +coolscan2 "Nikon" "LS 40 ED" "USB" +coolscan2 "Nikon" "LS 4000 ED" "IEEE1394" +coolscan2 "Nikon" "LS 8000 ED" "IEEE1394" +dc210 "Kodak" "DC210" "Serial port" +dc240 "Kodak" "DC240" "Serial port" +dc25 "Kodak" "DC25" "Serial port" +dc25 "Kodak" "DC20" "Serial port" +dmc "Polaroid" "DMC" "SCSI" +epson "Epson" "GT-5000" "Parport" +epson "Epson" "Actionscanner II" "Parport" +epson "Epson" "GT-6000" "SCSI Parport" +epson "Epson" "ES-300C" "SCSI Parport" +epson "Epson" "GT-5500" "SCSI" +epson "Epson" "GT-6500" "Parport" +epson "Epson" "ES-600C" "Parport" +epson "Epson" "ES-1200C" "Parport" +epson "Epson" "GT-7000" "SCSI" +epson "Epson" "GT-8000" "SCSI" +epson "Epson" "ES-8500" "SCSI" +epson "Epson" "Perfection 636S" "SCSI" +epson "Epson" "Perfection 636U" "USB" +epson "Epson" "Perfection 610" "USB" +epson "Epson" "Perfection 640" "USB" +epson "Epson" "Perfection 1200S" "SCSI" +epson "Epson" "Perfection 1200U" "USB" +epson "Epson" "Perfection 1200Photo" "USB" +epson "Epson" "Perfection 1240" "SCSI USB" +epson "Epson" "Perfection 1640" "SCSI USB" +epson "Epson" "Perfection 1650" "USB" +epson "Epson" "Perfection 1660" "USB" +epson "Epson" "Perfection 2400" "USB" +epson "Epson" "Perfection 2450" "USB IEEE-1394" +epson "Epson" "Perfection 3200" "USB" +epson "Epson" "Expression 636" "SCSI" +epson "Epson" "Expression 800" "SCSI" +epson "Epson" "Expression 1600" "SCSI USB IEEE-1394" +epson "Epson" "Expression 1680" "SCSI USB IEEE-1394" +epson "Epson" "FilmScan 200" "SCSI" +epson "Epson" "CX-3200" "USB" +epson "Epson" "CX-5200" "USB" +fujitsu "Fujitsu" "M3096G" "SCSI" +fujitsu "Fujitsu" "M3091DCd" "SCSI" +fujitsu "Fujitsu" "M3092DCd" "SCSI" +fujitsu "Fujitsu" "M3093GXim" "SCSI" +fujitsu "Fujitsu" "M3093GDim" "SCSI" +fujitsu "Fujitsu" "M4097" "SCSI" +fujitsu "Fujitsu" "fi-4340C" "SCSI" +gt68xx "Mustek" "BearPaw 1200 CS" "USB" +gt68xx "Mustek" "BearPaw 1200 CU" "USB" +gt68xx "Mustek" "BearPaw 1200 CU Plus" "USB" +gt68xx "Mustek" "BearPaw 1200 TA" "USB" +gt68xx "Mustek" "BearPaw 2400 CS" "USB" +gt68xx "Mustek" "BearPaw 2400 CS Plus" "USB" +gt68xx "Mustek" "BearPaw 2400 CU" "USB" +gt68xx "Mustek" "BearPaw 2400 CU Plus" "USB" +gt68xx "Mustek" "BearPaw 2400 TA" "USB" +gt68xx "Mustek" "BearPaw 2400 TA Plus" "USB" +gt68xx "Mustek" "ScanExpress 1200 UB Plus" "USB" +gt68xx "Mustek" "ScanExpress A3 USB" "USB" +gt68xx "Mustek" "ScanExpress 2400 USB" "USB" +gt68xx "Plustek" "OpticPro 1248U" "USB" +gt68xx "Plustek" "OpticPro UT16B" "USB" +gt68xx "Artec" "Ultima 2000" "USB" +gt68xx "Artec" "Ultima 2000 e+" "USB" +gt68xx "Boeder" "Sm@rtScan Slim Edition" "USB" +gt68xx "Packard Bell" "Diamond 1200" "USB" +gt68xx "Medion/Lifetec/Tevion/Cytron" "LT 9452" "USB" +gt68xx "Medion/Lifetec/Tevion/Cytron" "MD/LT 9375" "USB" +gt68xx "Medion/Lifetec/Tevion/Cytron" "MD/LT 9385" "USB" +gt68xx "Medion/Lifetec/Tevion/Cytron" "MD 9458" "USB" +gt68xx "Trust" "Flat Scan USB 19200" "USB" +gt68xx "Trust" "Compact Scan USB 19200" "USB" +gt68xx "Lexmark" "X70" "USB" +gt68xx "Lexmark" "X73" "USB" +gt68xx "Genius" "Colorpage Vivid3x" "USB" +hp "Hewlett-Packard" "ScanJet Plus" "Propietary" +hp "Hewlett-Packard" "ScanJet IIc" "SCSI" +hp "Hewlett-Packard" "ScanJet IIp" "SCSI" +hp "Hewlett-Packard" "ScanJet IIcx" "SCSI" +hp "Hewlett-Packard" "ScanJet 3c" "SCSI" +hp "Hewlett-Packard" "ScanJet 3p" "SCSI" +hp "Hewlett-Packard" "ScanJet 4c" "SCSI" +hp "Hewlett-Packard" "ScanJet 4p" "SCSI" +hp "Hewlett-Packard" "ScanJet 4100C" "USB" +hp "Hewlett-Packard" "ScanJet 5p" "SCSI" +hp "Hewlett-Packard" "ScanJet 5100C" "Parport" +hp "Hewlett-Packard" "ScanJet 5200C" "Parport USB" +hp "Hewlett-Packard" "ScanJet 6100C" "SCSI" +hp "Hewlett-Packard" "ScanJet 6200C" "SCSI USB" +hp "Hewlett-Packard" "ScanJet 6250C" "SCSI USB" +hp "Hewlett-Packard" "ScanJet 6300C" "SCSI USB" +hp "Hewlett-Packard" "ScanJet 6350C" "SCSI USB" +hp "Hewlett-Packard" "ScanJet 6390C" "SCSI USB" +hp "Hewlett-Packard" "PhotoSmart PhotoScanner" "SCSI" +hpsj5s "Hewlett-Packard" "ScanJet 5s" "Parport (EPP)" +leo "LEO" "LEOScan S3" "SCSI" +leo "Across Technologies" "FS-1130" "SCSI" +leo "Genius" "FS-1130 Colorpage Scanner" "SCSI" +matsushita "Panasonic" "KV-SS25" "SCSI" +matsushita "Panasonic" "KV-SS25D" "SCSI" +matsushita "Panasonic" "KV-SS50" "SCSI" +matsushita "Panasonic" "KV-SS55" "SCSI" +matsushita "Panasonic" "KV-SS50EX" "SCSI" +matsushita "Panasonic" "KV-SS55EX" "SCSI" +matsushita "Panasonic" "KV-SS850" "SCSI" +matsushita "Panasonic" "KV-SS855" "SCSI" +microtek "Microtek" "Scanmaker E6" "SCSI" +microtek "Microtek" "Scanmaker E3" "SCSI" +microtek "Microtek" "Scanmaker E2" "SCSI" +microtek "Microtek" "Scanmaker 35t+" "SCSI" +microtek "Microtek" "Scanmaker 45t" "SCSI" +microtek "Microtek" "Scanmaker 35" "SCSI" +microtek "Microtek" "Scanmaker III" "SCSI" +microtek "Microtek" "Scanmaker IISP" "SCSI" +microtek "Microtek" "Scanmaker IIHR" "SCSI" +microtek "Microtek" "Scanmaker IIG" "SCSI" +microtek "Microtek" "Scanmaker II" "SCSI" +microtek "Microtek" "Scanmaker 600Z(S)" "SCSI" +microtek "Microtek" "Scanmaker 600G(S)" "SCSI" +microtek "Microtek" "Color PageWiz" "SCSI (Parport)" +microtek "Agfa" "Arcus II" "SCSI" +microtek "Agfa" "StudioScan" "SCSI" +microtek "Agfa" "StudioScan II" "SCSI" +microtek "Agfa" "StudioScan IIsi" "SCSI" +microtek "Agfa" "DuoScan" "SCSI" +microtek2 "Microtek" "ScanMaker E3plus" "Parport" +microtek2 "Microtek" "ScanMaker E3plus" "SCSI" +microtek2 "Microtek" "ScanMaker X6" "SCSI" +microtek2 "Microtek" "ScanMaker X6EL" "SCSI" +microtek2 "Microtek" "ScanMaker X6USB" "USB" +microtek2 "Microtek" "ScanMaker V300" "SCSI" +microtek2 "Microtek" "ScanMaker V300" "Parport" +microtek2 "Microtek" "ScanMaker V310" "SCSI" +microtek2 "Microtek" "ScanMaker V310" "Parport" +microtek2 "Microtek" "ScanMaker V600" "SCSI" +microtek2 "Microtek" "ScanMaker V600" "Parport" +microtek2 "Microtek" "ScanMaker 330" "SCSI" +microtek2 "Microtek" "ScanMaker 630" "SCSI" +microtek2 "Microtek" "ScanMaker 636" "SCSI" +microtek2 "Microtek" "ScanMaker 9600XL" "SCSI" +microtek2 "Microtek" "ScanMaker 9600XL" "SCSI" +microtek2 "Microtek" "Phantom 330CX" "Parport" +microtek2 "Microtek" "SlimScan C3" "Parport" +microtek2 "Microtek" "Phantom 636" "SCSI" +microtek2 "Microtek" "Phantom 636CX" "Parport" +microtek2 "Microtek" "SlimScan C6" "USB" +microtek2 "Microtek" "ScanMaker V6USL" "SCSI" +microtek2 "Microtek" "ScanMaker V6USL" "USB" +microtek2 "Microtek" "ScanMaker X12USL" "SCSI" +microtek2 "Vobis" "HighScan" "SCSI" +microtek2 "Scanport" "SQ300" "Parport?" +microtek2 "Scanport" "SQ2030" "Parport" +microtek2 "Scanport" "SQ4836" "SCSI" +mustek "Mustek" "Paragon MFS-6000CX" "SCSI" +mustek "Mustek" "Paragon MFS-12000CX" "SCSI" +mustek "Mustek" "Paragon MFC-600S" "SCSI" +mustek "Mustek" "Paragon 600 II CD" "SCSI" +mustek "Mustek" "ScanMagic 600 II SP" "SCSI" +mustek "Mustek" "Paragon MFC-800S" "SCSI" +mustek "Mustek" "Paragon 800 II SP" "SCSI" +mustek "Mustek" "Paragon MFS-6000SP" "SCSI" +mustek "Mustek" "Paragon MFS-8000SP" "SCSI" +mustek "Mustek" "Paragon MFS-1200SP" "SCSI" +mustek "Mustek" "Paragon MFS-12000SP" "SCSI" +mustek "Mustek" "ScanExpress 6000SP" "SCSI" +mustek "Mustek" "ScanExpress 12000SP" "SCSI" +mustek "Mustek" "ScanExpress 12000SP Plus" "SCSI" +mustek "Mustek" "Paragon 1200 III SP" "SCSI" +mustek "Mustek" "Paragon 1200 LS" "SCSI" +mustek "Mustek" "ScanMagic 9636S" "SCSI" +mustek "Mustek" "ScanMagic 9636S Plus" "SCSI" +mustek "Mustek" "ScanExpress A3 SP" "SCSI" +mustek "Mustek" "Paragon 1200 SP Pro" "SCSI" +mustek "Mustek" "Paragon 1200 A3 Pro" "SCSI" +mustek "Mustek" "Paragon 600 II N" "Proprietary" +mustek "Trust" "Imagery 1200" "SCSI" +mustek "Trust" "Imagery 1200 SP" "SCSI" +mustek "Trust" "Imagery 4800 SP" "SCSI" +mustek "Trust" "SCSI Connect 19200" "SCSI" +mustek "Trust" "SCSI excellence series 19200" "SCSI" +mustek "Primax" "Compact 4800 SCSI" "SCSI" +mustek_pp "Mustek" "ScanExpress 6000 P" "Parport (EPP)" +mustek_pp "Mustek" "ScanExpress 600 SEP" "Parport (EPP)" +mustek_pp "Mustek" "ScanMagic 4800 P" "Parport (EPP)" +mustek_pp "Mustek" "600 III EP Plus" "Parport (EPP)" +mustek_pp "Mustek" "ScanExpress 600 CP" "Parport (EPP)" +mustek_pp "Mustek" "ScanMagic 600 CP" "Parport (EPP)" +mustek_pp "Mustek" "1200 CP" "Parport (EPP)" +mustek_pp "Mustek" "1200 CP+" "Parport (EPP)" +mustek_pp "Medion/Tevion/LifeTec" "MD 9848" "Parport (EPP)" +mustek_pp "Medion/Tevion/LifeTec" "MD/LT 935x" "Parport (EPP)" +mustek_pp "Medion/Tevion/LifeTec" "MD/LT 985x" "Parport (EPP)" +mustek_pp "Medion/Tevion/LifeTec" "MD/LT 9890" "Parport (EPP)" +mustek_pp "Targa" "Funline TS12 EP" "Parport (EPP)" +mustek_pp "Targa" "Funline TS6 EP" "Parport (EPP)" +mustek_pp "Trust Easy Connect" "9600+" "Parport (EPP)" +mustek_pp "Viviscan" "Compact II" "Parport (EPP)" +mustek_pp "Cybercom" "9352" "Parport (EPP)" +mustek_pp "Gallery" "4800" "Parport (EPP)" +mustek_usb "Mustek" "ScanExpress 600 CU" "USB" +mustek_usb "Mustek" "ScanExpress 1200 CU" "USB" +mustek_usb "Mustek" "ScanExpress 1200 CU Plus" "USB" +mustek_usb "Mustek" "ScanExpress 1200 UB" "USB" +mustek_usb "Trust" "Compact Scan USB 19200" "USB" +nec "NEC" "PC-IN500/4C" "SCSI" +pie "Devcom" "9636PRO" "SCSI" +pie "Devcom" "9636S" "SCSI" +pie "Devcom" "9630S" "SCSI" +pie "PIE" "ScanAce 1236S" "SCSI" +pie "PIE" "ScanAce 1230S" "SCSI" +pie "PIE" "ScanAce II" "SCSI" +pie "PIE" "ScanAce III" "SCSI" +pie "PIE" "ScanAce Plus" "SCSI" +pie "PIE" "ScanAce II Plus" "SCSI" +pie "PIE" "ScanAce III Plus" "SCSI" +pie "PIE" "ScanAce V" "SCSI" +pie "PIE" "ScanAce ScanMedia" "SCSI" +pie "PIE" "ScanAce ScanMedia II" "SCSI" +pie "PIE" "ScanAce 630S" "SCSI" +pie "PIE" "ScanAce 636S" "SCSI" +pie "Adlib" "JetScan630" "SCSI" +pie "Adlib" "JetScan636PRO" "SCSI" +plustek "Plustek" "OpticPro 4800P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 4830P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 600P/6000P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 4831P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9630P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9630PL" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9600P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 1236P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 12000P/96000P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9636P" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9636P+/Turbo" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 9636T" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro 12000T" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro AI3" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro P8" "Parport" +plustek "Plustek" "OpticPro P12" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro PT12" "Parport (SPP, EPP)" +plustek "Plustek" "OpticPro U12" "USB" +plustek "Plustek" "OpticPro UT12" "USB" +plustek "Plustek" "OpticPro UT16" "USB" +plustek "Plustek" "OpticPro U24" "USB" +plustek "Plustek" "OpticPro UT24" "USB" +plustek "Plustek" "OpticPro 19200S" "SCSI" +plustek "Primax" "Colorado 4800" "Parport (SPP, EPP)" +plustek "Primax" "Compact 4800 Direct" "Parport (SPP, EPP)" +plustek "Primax" "Compact 4800 Direct-30" "Parport (SPP, EPP)" +plustek "Primax" "Compact 9600 Direct-30" "Parport (SPP, EPP)" +plustek "Genius" "Colorpage Vivid III V2" "Parport (SPP, EPP)" +plustek "Genius" "Colorpage Vivid Pro II Film" "Parport (SPP, EPP)" +plustek "Genius" "Colorpage HR6 V2" "USB" +plustek "Genius" "Colorpage HR7" "USB" +plustek "Genius" "Colorpage HR6A" "USB" +plustek "Genius" "Colorpage HR7LE" "USB" +plustek "Genius" "Colorpage HR6X" "USB" +plustek "Aries" "Scan-It Pro 4800" "Parport (SPP, EPP)" +plustek "BrightScan" "BrighScan OpticPro" "Parport (SPP, EPP)" +plustek "Mustek" "BearPaw 1200" "USB" +plustek "Mustek" "BearPaw 2400" "USB" +plustek "Hewlett-Packard" "ScanJet 2100C" "USB" +plustek "Hewlett-Packard" "ScanJet 2200C" "USB" +plustek "Epson" "Perfection 1250" "USB" +plustek "Epson" "Perfection 1250Photo" "USB" +plustek "Epson" "Perfection 1260" "USB" +plustek "Epson" "Perfection 1260Photo" "USB" +plustek "Umax" "UMAX 3400" "USB" +plustek "Umax" "UMAX 5400" "USB" +plustek "Canon" "CanoScan N650U/N656U" "USB" +plustek "Canon" "CanoScan N1220U" "USB" +plustek "Canon" "CanoScan N670U/N676U" "USB" +plustek "Canon" "CanoScan N1240U" "USB" +plustek "Canon" "CanoScan LiDE20" "USB" +plustek "Canon" "CanoScan LiDE30" "USB" +qcam "Connectix" "Color QuickCam" "Parport" +qcam "Connectix" "Greyscale QuickCam" "Parport" +ricoh "Ricoh" "Ricoh IS50" "SCSI" +ricoh "Ricoh" "Ricoh IS60" "SCSI" +s9036 "Siemens" "9036 Flatbed scanner" "SCSI" +sceptre "Sceptre" "Vividscan S1200" "SCSI" +sceptre "Komodo" "S1200" "SCSI" +sharp "Sharp" "JX-610" "SCSI" +sharp "Sharp" "JX-250" "SCSI" +sharp "Sharp" "JX-320" "SCSI" +sharp "Sharp" "JX-325" "SCSI" +sharp "Sharp" "JX-330" "SCSI" +sharp "Sharp" "JX-350" "SCSI" +sm3600 "Microtek" "ScanMaker 3600" "USB" +sm3600 "Microtek" "ScanMaker 3700" "USB" +sm3600 "Microtek" "ScanMaker 3750" "USB" +SnapScan "AGFA" "SnapScan 300" "SCSI" +SnapScan "AGFA" "SnapScan 310" "SCSI" +SnapScan "AGFA" "SnapScan 600" "SCSI" +SnapScan "AGFA" "SnapScan 1236s" "SCSI" +SnapScan "AGFA" "SnapScan 1236u" "USB" +SnapScan "AGFA" "SnapScan 1212u" "USB" +SnapScan "AGFA" "SnapScan e10" "USB" +SnapScan "AGFA" "SnapScan e20" "USB" +SnapScan "AGFA" "SnapScan e25" "USB" +SnapScan "AGFA" "SnapScan e26" "USB" +SnapScan "AGFA" "SnapScan e40" "USB" +SnapScan "AGFA" "SnapScan e42" "USB" +SnapScan "AGFA" "SnapScan e50" "USB" +SnapScan "AGFA" "SnapScan e52" "USB" +SnapScan "AGFA" "SnapScan e60" "USB" +SnapScan "Benq" "300f" "SCSI" +SnapScan "Benq" "310s" "SCSI" +SnapScan "Benq" "610s" "SCSI" +SnapScan "Benq" "610plus" "SCSI" +SnapScan "Benq" "620s" "SCSI" +SnapScan "Benq" "310u" "USB" +SnapScan "Benq" "320u" "USB" +SnapScan "Benq" "340u" "USB" +SnapScan "Benq" "620u" "USB" +SnapScan "Benq" "640u" "USB" +SnapScan "Benq" "640bu" "USB" +SnapScan "Benq" "1240" "USB" +SnapScan "Benq" "3300" "USB" +SnapScan "Benq" "4300" "USB" +SnapScan "Benq" "5000" "USB" +SnapScan "Benq" "5300" "USB" +SnapScan "Guillemot / Hercules" "Maxi Scan A4 Deluxe (SCSI)" "SCSI" +SnapScan "Guillemot / Hercules" "Scan@home Touch 1248 (USB)" "USB" +SnapScan "Mitsubishi" "Diamondview 648UT" "USB" +SnapScan "Mitsubishi" "Diamondview 650U" "USB" +sp15c "Fujitsu" "SP15C" "SCSI" +st400 "Siemens" "ST400" "SCSI" +st400 "Siemens" "ST800" "SCSI" +tamarack "Tamarack" "Artiscan 6000C" "SCSI" +tamarack "Tamarack" "Artiscan 8000C" "SCSI" +tamarack "Tamarack" "Artiscan 12000C" "SCSI" +teco1 "Relisys" "RELI 2412" "SCSI" +teco1 "Relisys" "AVEC 2400" "SCSI" +teco1 "Relisys" "RELI 4830" "SCSI" +teco1 "Relisys" "AVEC 2412" "SCSI" +teco1 "Relisys" "AVEC 4800" "SCSI" +teco1 "Relisys" "AVEC 4816" "SCSI" +teco1 "Relisys" "RELI DS6" "SCSI" +teco1 "Relisys" "RELI DS15" "SCSI" +teco1 "Relisys" "RELI 2400" "SCSI" +teco1 "Relisys" "RELI 4816" "SCSI" +teco1 "Relisys" "RELI 9600" "SCSI" +teco1 "Relisys" "RELI 9612" "SCSI" +teco1 "Relisys" "RELI 9624" "SCSI" +teco1 "Relisys" "RELI 9630" "SCSI" +teco1 "Actown" "ACT Scan I 30" "SCSI" +teco1 "Dextra" "DF-600P" "SCSI" +teco1 "Dextra" "DF-1200T+" "SCSI" +teco1 "Dextra" "DF-4830T" "SCSI" +teco1 "Dextra" "DF-9624" "SCSI" +teco2 "Relisys" "AVEC Super 3" "SCSI" +teco2 "Relisys" "SCORPIO Super 3" "SCSI" +teco2 "Relisys" "APOLLO Express 6" "SCSI" +teco2 "Relisys" "SCORPIO Pro" "SCSI" +teco2 "Relisys" "SCORPIO Pro-S" "SCSI" +teco2 "Primax" "Profi 9600" "SCSI" +teco2 "Primax" "Profi 19200" "SCSI" +teco3 "Relisys" "Infinity Scorpio" "SCSI" +teco3 "Plustek" "OpticPro 2400SP" "SCSI" +teco3 "PIOTECH" "Splendeur 3024" "SCSI" +teco3 "Trust" "Imagery 2400 SP" "SCSI" +teco3 "Trust" "Imagery 4800 SP+" "SCSI" +teco3 "Trust" "Imagery 9600 SP" "SCSI" +umax "UMAX" "Vista S6" "SCSI" +umax "UMAX" "Vista S6E" "SCSI" +umax "UMAX" "UMAX S-6E" "SCSI" +umax "UMAX" "UMAX S-6EG" "SCSI" +umax "UMAX" "Vista-S8" "SCSI" +umax "UMAX" "Supervista S-12" "SCSI" +umax "UMAX" "UMAX S-12" "SCSI" +umax "UMAX" "UMAX S-12G" "SCSI" +umax "UMAX" "Astra 600S" "SCSI" +umax "UMAX" "Astra 610S" "SCSI" +umax "UMAX" "Astra 1200S" "SCSI" +umax "UMAX" "Astra 1220S" "SCSI" +umax "UMAX" "Astra 2100S" "SCSI" +umax "UMAX" "Astra 2200 (SU)" "SCSI" +umax "UMAX" "Astra 2200 (SU)" "USB" +umax "UMAX" "Astra 2400S" "SCSI" +umax "UMAX" "Astra 6400" "IEEE-1394" +umax "UMAX" "Astra 6450" "IEEE-1394" +umax "UMAX" "Astra MX3" "SCSI" +umax "UMAX" "Astra MX3" "USB" +umax "UMAX" "Mirage D-16L" "SCSI" +umax "UMAX" "Mirage II" "SCSI" +umax "UMAX" "Mirage IIse" "SCSI" +umax "UMAX" "PSD" "SCSI" +umax "UMAX" "PowerLook" "SCSI" +umax "UMAX" "PL-II" "SCSI" +umax "UMAX" "PowerLook III" "SCSI" +umax "UMAX" "PowerLook 270" "SCSI" +umax "UMAX" "PowerLook 270plus" "SCSI" +umax "UMAX" "PowerLook 1100" "IEEE-1394" +umax "UMAX" "PowerLook 2000" "SCSI" +umax "UMAX" "PowerLook 2100XL" "SCSI" +umax "UMAX" "PowerLook 3000" "SCSI" +umax "UMAX" "Gemini D-16" "SCSI" +umax "UMAX" "UMAX VT600" "SCSI" +umax "UMAX" "Vista-T630" "SCSI" +umax "UMAX" "UC 630" "SCSI" +umax "UMAX" "UG 630" "SCSI" +umax "UMAX" "UG 80" "SCSI" +umax "UMAX" "UC 840" "SCSI" +umax "UMAX" "UC 1200S" "SCSI" +umax "UMAX" "UC 1200SE" "SCSI" +umax "UMAX" "UC 1260" "SCSI" +umax "Linotype Hell" "Jade" "SCSI" +umax "Linotype Hell" "Jade" "SCSI" +umax "Linotype Hell" "Jade2" "SCSI" +umax "Linotype Hell" "Saphir" "SCSI" +umax "Linotype Hell" "Saphir2" "SCSI" +umax "Linotype Hell" "Saphir3" "SCSI" +umax "Linotype Hell" "Saphir Ultra" "SCSI" +umax "Linotype Hell" "Saphir Ultra II" "SCSI" +umax "Linotype Hell" "Saphir HiRes" "SCSI" +umax "Linotype Hell" "Opal" "SCSI" +umax "Linotype Hell" "Opal Ultra" "SCSI" +umax "Linotype Hell" "Linoscan 1400" "SCSI" +umax "Vobis" "Highscreen Scanboostar Premium" "SCSI" +umax "EDGE" "KTX-9600US" "SCSI" +umax "Epson" "Perfection 600" "SCSI" +umax "Escom" "Image Scanner 256" "SCSI" +umax "Escort" "Galleria 600" "SCSI" +umax "Genius" "ColorPage-HR5 (Pro)" "SCSI" +umax "Nikon" "AX-110 / Scantouch 110" "SCSI" +umax "Nikon" "AX-210" "SCSI" +umax1220u "UMAX" "Astra 1220U" "USB" +umax1220u "UMAX" "Astra 2000U" "USB" +umax1220u "UMAX" "Astra 2200U" "USB" +umax_pp "UMAX" "Astra 1220P" "Parport (EPP)" +umax_pp "UMAX" "Astra 2000P" "Parport (EPP)" +umax_pp "UMAX" "Astra 1600P" "Parport (EPP)" +umax_pp "UMAX" "Astra 610P" "Parport (EPP)" +umax_pp "Hewlett-Packard" "Scanjet 3200C" "Parport (EPP)" diff --git a/include/setup_checks.inc b/include/setup_checks.inc new file mode 100644 index 000000000..2c097bd4b --- /dev/null +++ b/include/setup_checks.inc @@ -0,0 +1,1167 @@ += $minver){ + return (true); + } + + return (false); +} + + +function check_schema_version($description, $version) +{ + $desc= preg_replace("/^.* DESC\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $description); + + return preg_match("/\(v$version\)/", $desc); +} + +function view_schema_check($table) +{ + $message=""; + foreach ($table as $key => $msg){ + $message.= ""; + } + else + { + $message.="";} + } + $message.="
$msg"; + if(strstr($msg,"enabled")) { + $message.="true
false
"; + return $message; +} + +function schema_check($server, $admin, $password,$aff=0) +{ + global $config; + + $messages= array(); + $required_classes= array( + "gosaObject" => array("version" => "2.1"), + "gosaAccount" => array("version" => "2.1.2"), + "gosaLockEntry" => array("version" => "2.1"), + "gosaCacheEntry" => array("version" => "2.1"), + "gosaDepartment" => array("version" => "2.1"), + + "goFaxAccount" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"), + "goFaxSBlock" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"), + "goFaxRBlock" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"), + + "gosaUserTemplate" => array("version" => "2.1", "class" => "posixAccount","file" => "nis.schema"), + "gosaMailAccount" => array("version" => "2.1", "class" => "mailAccount","file" => "gosa+samba3.schema"), + "gosaProxyAccount" => array("version" => "2.1.2", "class" => "proxyAccount","file" => "gosa+samba3.schema"), + "gosaApplication" => array("version" => "2.1", "class" => "appgroup","file" => "gosa.schema"), + "gosaApplicationGroup" => array("version" => "2.1", "class" => "appgroup","file" => "gosa.schema"), + + "GOhard" => array("version" => "2.1", "class" => "terminals","file" => "goto.schema"), + "gotoTerminal" => array("version" => "2.0", "class" => "terminals","file" => "goto.schema"), + "goServer" => array("version" => "2.1","class" => "server","file" => "goserver.schema"), + "goTerminalServer" => array("version" => "2.1", "class" => "terminals","file" => "goto.schema"), + "goNfsServer" => array("version" => "2.1", "class" => "terminals","file" => "goto.schema"), + "goNtpServer" => array("version" => "2.1", "class" => "terminals","file" => "goto.schema"), + "goSyslogServer" => array("version" => "2.1", "class" => "terminals","file" => "goto.schema"), + "goLdapServer" => array("version" => "2.1"), + "goCupsServer" => array("version" => "2.1", "class" => array("posixAccount", "terminals"),), + "goImapServer" => array("version" => "2.1", "class" => array("mailAccount", "mailgroup"),"file" => "gosa+samba3.schema"), + "goKrbServer" => array("version" => "2.1"), + "goFaxServer" => array("version" => "2.1", "class" => "gofaxAccount","file" => "gofax.schema") + ); + + /* Build LDAP connection */ + $ds= ldap_connect ($server); + if (!$ds) { + return (array(_("Can't bind to LDAP. No schema check possible!"))); + } + ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); + $r= ldap_bind ($ds, $admin, $password); + + /* Get base to look for schema */ + $sr = @ldap_read ($ds, "", "objectClass=*", array("subschemaSubentry")); + $attr= @ldap_get_entries($ds,$sr); + if (!isset($attr[0]['subschemasubentry'][0])){ + return (array(_("Can't get schema information from server. No schema check possible!"))); + } + + /* Get list of objectclasses */ + $nb= $attr[0]['subschemasubentry'][0]; + $objectclasses= array(); + $sr= ldap_read ($ds, $nb, "objectClass=*", array("objectclasses")); + $attrs= ldap_get_entries($ds,$sr); + if (!isset($attrs[0])){ + return (array(_("Can't get schema information from server. No schema check possible!"))); + } + foreach ($attrs[0]['objectclasses'] as $val){ + $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val); + if ($name != $val){ + $objectclasses[$name]= $val; + } + } + /* Walk through objectclasses and check if they are needed or not */ + foreach ($required_classes as $key => $value){ + if (isset($value['class'])){ + if (!is_array($value['class'])){ + $classes= array($value['class']); + } else { + $classes= $value['class']; + } + + /* Check if we are using the class that requires */ + foreach($classes as $class){ + if (!isset($objectclasses[$key])){ + $messages[$key]= sprintf(_("Optional objectclass '%s' required by plugin '%s' is not present in LDAP setup"), $key, $class); + } else { + if (!check_schema_version($objectclasses[$key], $value['version'])){ + $messages[$key]= sprintf(_("Optional objectclass '%s' required by plugin '%s' does not have version %s"), $key, $class, $value['version']); + }else { + if(!isset($affich2[$class])){ + $affich2[$class]="Support for $class enabled ".$value['file'].""; + } + } + } + + } + } else { + /* Required class */ + if (!isset($objectclasses[$key])){ + $messages[$key]= sprintf(_("Required objectclass '%s' is not present in LDAP setup"), $key); + } else { + if (!check_schema_version($objectclasses[$key], $value['version'])){ + $messages[$key]= sprintf(_("Required objectclass '%s' does not have version %s"), $key, $value['version']); + } + } + } + } + + /* Check for correct samba parameters */ + if (!isset($objectclasses['sambaSamAccount'])){ + $messages['samba3']= _("SAMBA 3 support disabled, no schema seems to be installed"); + $affich['samba3']= $messages['samba3']."gosa+samba3.schema"; + }else{$affich['samba3']=_("SAMBA 3 support enabledgosa+samba3.schema");} + + if (!isset($objectclasses['sambaAccount'])){ + $messages['samba2']= _("SAMBA 2 support disabled, no schema seems to be installed"); + $affich['samba2']=$messages['samba2']."samba.schema"; + }else{$affich['samba2']=_("SAMBA 2 support enabledsamba.schema");} + + /* Check pureftp/dns/ */ + if (!isset($objectclasses['PureFTPdUser'])){ + $messages['pureftp']= _("Support for pureftp disabled, no schema seems to be installed"); + $affich['pureftp']= $messages['pureftp']."pureftpd.schema"; + }else{$affich['pureftp']=_("Support for pureftp enabledpureftpd.schema");} + + if (!isset($objectclasses['gosaWebdavAccount'])){ + $messages['webdav']= _("Support for WebDAV disabled, no schema seems to be installed"); + $affich['webdav']=$messages['webdav'].""; + }else{$affich['webdav']=_("Support for WebDAV enabledgosa+samba3.schema");} + + if (!isset($objectclasses['phpgwAccount'])){ + $messages['phpgroupware']= _("Support for phpgroupware disabled, no schema seems to be installed"); + $affich['phpgroupware']=$messages['phpgroupware']."phpgwaccount.schema"; + }else{$affich['phpgroupware']=_("Support for phpgroupware enabledphpgwaccount.schema");} + + if (!isset($objectclasses['goFonAccount'])){ + $messages['phoneaccount']= _("Support for gofon disabled, no schema seems to be installed"); + $affich['phoneaccount']=$messages['phoneaccount']."gofon.schema"; + }else{$affich['phoneaccount']=_("Support for gofon enabledgofon.schema");} + + if($aff==0)return ($messages); + else return(array_merge($affich,$affich2)); +} + + + +function check(&$faults, $message, $description, $test, $required= TRUE) +{ + $msg= "
$message"; + if ($test){ + $msg.= _("OK")."
"; + } else { + if (!$required){ + $msg.=""._("Ignored")."
"; + } else { + $msg.=""._("Failed")."
"; + $faults++; + } + } + $msg.= "
$description

"; + + return $msg; +} + +function perform_php_checks(&$faults) +{ + global $check_globals; + + $faults= 0; + $msg= ""; + + $msg.= "

"._("PHP setup inspection")."

"; + $msg.= check ( $faults, _("Checking for PHP version (>=4.1.0)"), + _("PHP must be of version 4.1.0 or above for some functions and known bugs in PHP language."), + minimum_version('4.1.0')); + + $msg.= check ( $faults, _("Checking if register_globals is set to 'off'"), + _("register_globals is a PHP mechanism to register all global varibales to be accessible from scripts without changing the scope. This may be a security risk. GOsa will run in both modes."), + $check_globals == 0, FALSE); + + $msg.= check ( $faults, _("Checking for ldap module"), + _("This is the main module used by GOsa and therefore really required."), + function_exists('ldap_bind')); + + $msg.= check ( $faults, _("Checking for gettext support"), + _("Gettext support is required for internationalized GOsa."), function_exists('bindtextdomain')); + + $msg.= check ( $faults, _("Checking for mhash module"), + _("To use SSHA encryption, you'll need this module. If you are just using crypt or md5 encryption, ignore this message. GOsa will run without it."), + function_exists('mhash'), FALSE); + + $msg.= check ( $faults, _("Checking for imap module"), + _("The IMAP module is needed to communicate with the IMAP server. It gets status informations, creates and deletes mail users."), + function_exists('imap_open')); + $msg.= check ( $faults, _("Checking for getacl in imap"), + _("The getacl support is needed for shared folder permissions. The standard IMAP module is not capable of reading acl's. You need a recend PHP version for this feature."), + function_exists('imap_getacl'), FALSE); + $msg.= check ( $faults, _("Checking for mysql module"), + _("MySQL support is needed for reading GOfax reports from databases."), + function_exists('mysql_query'), FALSE); + $msg.= check ( $faults, _("Checking for cups module"), + _("In order to read available printers from IPP protocol instead of printcap files, you've to install the CUPS module."), + function_exists('cups_get_dest_list'), FALSE); + $msg.= check ( $faults, _("Checking for kadm5 module"), + _("Managing users in kerberos requires the kadm5 module which is downloadable via PEAR network."), + function_exists('kadm5_init_with_password'), FALSE); + return ($msg); +} + + +function perform_additional_checks(&$faults) +{ +# Programm check + $msg= "

"._("Checking for some additional programms")."

"; + +# Image Magick + $query= "LC_ALL=C LANG=C convert -help"; + $output= shell_exec ($query); + if ($output != ""){ + $lines= split ("\n", $output); + $version= preg_replace ("/^Version:[^I]+ImageMagick ([^\s]+).*/", "\\1", $lines[0]); + list($major, $minor)= split("\.", $version); + $msg.= check ( $faults, _("Checking for ImageMagick (>=5.4.0)"), + _("ImageMagick is used to convert user supplied images to fit the suggested size and the unified JPEG format."), + ($major > 5 || ($major == 5 && $minor >= 4))); + } else { + $msg.= check ( $faults, _("Checking imagick module for PHP"), + _("Imagick is used to convert user supplied images to fit the suggested size and the unified JPEG format from PHP script."), function_exists('imagick_blob2image'), TRUE); + } + +# Check for fping + $query= "LC_ALL=C LANG=C fping -v 2>&1"; + $output= shell_exec ($query); + $have_fping= preg_match("/^fping:/", $output); + $msg.= check ( $faults, _("Checking for fping utility"), + _("The fping utility is only used if you've got a thin client based terminal environment running."), + $have_fping, FALSE); + +# Check for smb hash generation tool + $query= "mkntpwd 2>&1"; + $output= shell_exec ($query); + $have_mkntpwd= preg_match("/^Usage: mkntpwd /", $output); + $alt = 0; + + if (!$have_mkntpwd){ + $query= "LC_ALL=C LANG=C perl -MCrypt::SmbHash -e 'ntlmgen \"PASSWD\", \$lm, \$nt; print \"\${lm}:\${nt}\\n\";' &>/dev/null"; + system ($query, $ret); + $alt= ($ret == 0); + } + + $msg.= check ( $faults, _("Checking for a way to generate LM/NT password hashes"), + _("In order to use SAMBA 2/3, you've to install some additional packages to generate password hashes."), + ($have_mkntpwd || $alt)); +# checking for some PHP.ini Options + +/* seesio.auto_start should be off, in order to without trouble*/ + +$arra = ini_get_all(); + +/* This array contains folling info now : + global_value 0 + local_value 0 + access 7 + +-->Access types +PHP_INI_USER 1 Entry can be set in user scripts +PHP_INI_PERDIR 2 Entry can be set in php.ini, .htaccess or httpd.conf +PHP_INI_SYSTEM 4 Entry can be set in php.ini or httpd.conf +PHP_INI_ALL 7 Entry can be set anywhere + +*/ + +$session_auto_start = ($arra['session.auto_start']); +$implicit_flush = ($arra['implicit_flush']); +$max_execution_time = ($arra['max_execution_time']); +$memory_limit = ($arra['memory_limit']); +$expose_php = ($arra['expose_php']); +$magic_quotes_gpc = ($arra['magic_quotes_gpc']); +$register_globals = ($arra['register_globals']); + + +// auto_register +$msg.= check ( $faults, _("PHP.ini check -> session.auto_register"), + _("In Order to use GOsa without any trouble, the session.auto_register option in your php.ini musst be 'Off'."), + (!$session_auto_start['local_value'])); + + + +//implicit_flush +$msg.= check ( $faults, _("PHP.ini check -> implicit_flush"), + _("This Option defines the Ouput handling, turn this Option off, to increase performance."), + !$implicit_flush['local_value'],0,false); + +//max_execution_time +if($max_execution_time['local_value'] < 30 ) + $max_execution_time['local_value']=false; +$msg.= check ( $faults, _("PHP.ini check -> max_execution_time"), + _("The Execution time, should be 30 seconds minimun, cause some actions will need huge ammount of time ."), + $max_execution_time['local_value'],0,false); + +//memory_limit +if($memory_limit['local_value'] < 8 ) + $memory_limit['local_value']=false; +$msg.= check ( $faults, _("PHP.ini check -> memory_limit"), + _("GOsa need at least 8M of memory, less will cause unpredictable errors, sometimes without error message!. Best would be 32 M here."), + !$implicit_flush['local_value'],0,false); + +//expose_php +$msg.= check ( $faults, _("PHP.ini check -> expose_php"), + _("PHP won't send any Information about the Server you are running, should be a security fact."), + !$implicit_flush['local_value'],0,false); + +//magic_quotes_gpc +$msg.= check ( $faults, _("PHP.ini check -> magic_quotes_gpc"), + _("Security option, php will escape all quotes in strings ."), + $magic_quotes_gpc['local_value'],0,false); + + + + + + + + + + + + + + + + + return $msg; +} + + + +//! Added by Hickert +// +// Parse /contrib/gosa.conf to set user defined values +//This function may create the ldap.conf +// Lets try +function parse_contrib_conf() +{ + /* First gather all needed informations */ + + + + /* Variables */ + $str = ""; + $used_samba_version = 0; + $query = ""; + $fp = false; + $output = ""; + $needridbase_sid = false; + $pwdhash = ""; + $replacements = array(); + $ldapconf = $_SESSION['ldapconf']; // The Installation information + $classes = $_SESSION['classes']; // Class information needed to define which features are enabled + $possible_plugins = array(); + + if(isset($classes['samba3'])) // means Samba 3 is disabled + $used_samba_version = 2; + else + $used_samba_version = 3; + + + if(file_exists("/usr/lib/gosa/mkntpasswd")) { + $pwdhash = "/usr/lib/gosa/mkntpasswd"; + } + elseif (preg_match("/^Usage: mkntpwd /", shell_exec ("mkntpwd 2>&1"))) { + $pwdhash= "mkntpwd"; + } else { + $pwdhash=addslashes(' perl -MCrypt::SmbHash -e "ntlmgen \"\$ARGV[0]\", \$lm, \$nt; print \"\${lm}:\${nt}\n\";" $1'); + // $pwdhash= 'perl -MCrypt::SmbHash -e \"ntlmgen \\"\\$ARGV[0]\\", \\$lm, \\$nt; print \\"\\${lm}:\\${nt}\\\";\"'; + } + + + // Define which variables will be replaced + $replacements['{LOCATIONNAME}'] = $ldapconf['location']; + $replacements['{SAMBAVERSION}'] = $used_samba_version; + $replacements['{LDAPBASE}'] = $ldapconf['base']; + $replacements['{LDAPADMIN}'] = $ldapconf['admin']; + $replacements['{DNMODE}'] = $ldapconf['peopledn']; + $replacements['{LOCALHOST}'] = $ldapconf['uri']; + $replacements['{PASSWORD}'] = $ldapconf['password']; + $replacements['{CRYPT}'] = $ldapconf['arr_cryptkeys'][$ldapconf['arr_crypts']]; + $replacements['{SID}'] = ""; + $replacements['{RIDBASE}'] = ""; + $replacements['{MAILMETHOD}'] = $ldapconf['mail_methods'][$ldapconf['mail']]; + $replacements['{SMBHASH}'] = $pwdhash; + $replacements['{GOVERNMENTMODE}'] = "false"; + + + + + // This array contains all preg_replace syntax to delete all unused plugins + // THE kEY MUST BE THE CLASSNAME so we can check it with $ldapconf['classes'] + + $possible_plugins['fonreport'][] ="'\n.*.*\n'i"; + $possible_plugins['phoneaccount'][] ="'\n.*.*\n'i"; + + $possible_plugins['logview'][] ="'\n.*.*\n'i"; + + $possible_plugins['pureftp'][] ="'\n.*.*\n'i"; + + $possible_plugins['webdav'][] ="'\n.*.*\n'i"; + + $possible_plugins['phpgroupware'][] ="'\n.*'i"; + + + // Header information + // Needed to send the generated gosa.conf to the browser + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + header("Cache-Control: no-cache"); + header("Pragma: no-cache"); + header("Cache-Control: post-check=0, pre-check=0"); + header("Content-type: text/plain"); + + if (preg_match('/MSIE 5.5/', $_SERVER['HTTP_USER_AGENT']) || preg_match('/MSIE 6.0/', $_SERVER['HTTP_USER_AGENT'])) + { + header('Content-Disposition: filename="gosa.conf"'); + } else { + header('Content-Disposition: attachment; filename="gosa.conf"'); + } + + + if(!$fp=fopen(CONFIG_TEMPLATE_DIR."/gosa.conf","r")) + { + echo "Can't open file ".CONFIG_TEMPLATE_DIR."/gosa.conf"; + // Don't write anything else + } + else + { + // Read out Data ..... + while(!feof($fp)) + { + $str.= fread($fp,512); + } + + + // Lets check which samba version we will use + + // in case of samba 2 we don't need to add additional objets in gosa.conf + // in case of samba 3 we musst detect if theres an objectType = SambaObjekt defined + // if theres is one, then do nothing, because the setup will detect the the SID themself + // if theres none defined add SID and RIDBASE to gosa.conf + + + if($used_samba_version == 2) + { + // Do nothing ... + } + else + { + // Create LDAP connection, to check if theres a domain Objekt definen in the Ldap scheme + $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']); + + + // Try to find a Samba Domain Objekt + $ldap->search("(objectClass=sambaDomain)"); + + // Something found ??? so we need to define ridbase an SID by ourselfs + if($ldap->count()< 1) + { + $replacements['{SID}'] = "sid=\"123412-11\""; + $replacements['{RIDBASE}'] = "ridbase=\"1000\""; + } + }// else --> $used_samba_version == 2 + + // Data readed, types replaced, samba version detected and checked if we need to add SID and RIDBASE + + + // Check if there is an ivbbEntry in the LDAP tree, in this case we will set the governmentmode to true + // Create LDAP connection, to check if theres a domain Objekt definen in the Ldap scheme + + if(!isset($ldap)) + $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']); + + + // Try to find a Samba Domain Objekt + $ldap->search("(objectClass=ivbbEntry)"); + + // Something found ??? so we need to define ridbase an SID by ourselfs + if($ldap->count()> 0) + { + $replacements['{GOVERNMENTMODE}'] = "true"; + } + + + // Replace all colleted information with placeholder + foreach($replacements as $key => $val) + { + $str = preg_replace("/".$key."/",$val,$str); + // $str = ereg_replace($key,$val,$str); + } + + // Remove all unused plugins + foreach($possible_plugins as $plugin) + { + foreach($plugin as $key=>$val) + { + if(in_array($plugin,$classes)) + { + $str = preg_replace($val,"\n",$str); + } + } + } + + + }// else --> !$fp=fopen("../contrib/gosa.conf","r") + + return ( $str); +} + + +// This ist the first page shown in setup +// This page test some packages, like php version, ldap_module aso +// The funtion don't save anything, it tests only, when withoutput = false +// (called from setup.php); +function show_setup_page1($withoutput = true) +{ + $smarty = get_smarty(); + + $smarty->assign ("content", get_template_path('setup_introduction.tpl')); + $smarty->assign ("tests", perform_php_checks($faults)); + + + + // This var is true if there is anything went wrong + if ($faults) + { + $smarty->assign("mode", "disabled"); + } + + // This line displays the template only if (withoutput is set) + if($withoutput) + $smarty->display (get_template_path('headers.tpl')); + + if (isset($_SESSION['errors'])) + { + $smarty->assign("errors", $_SESSION['errors']); + } + + if($withoutput) + $smarty->display (get_template_path('setup.tpl')); + + return (!$faults); +} + + + + + + + +/* Shows Setup_page 2*/ +function show_setup_page2($withoutput = true) +{ + $smarty = get_smarty(); + + $smarty->assign ("content", get_template_path('setup_step2.tpl')); + $smarty->assign ("tests", perform_additional_checks($faults)); + + if ($faults) { + $smarty->assign("mode", "disabled"); + } + if($withoutput){ + $smarty->display (get_template_path('headers.tpl')); + } + + if (isset($_SESSION['errors'])) { + $smarty->assign("errors", $_SESSION['errors']); + } + if($withoutput){ + $smarty->display (get_template_path('setup.tpl')); + } + return (!$faults); +} + + +/* Setup page 3 asks for the server address + "Now we're going to include your LDAP server and create an initial configuration"*/ +function show_setup_page3($withoutput = true) +{ + + // Take the Post oder the Sessioin saved data + if(isset($_POST['uri'])) + $uri = $_POST['uri']; + elseif(isset($_SESSION['ldapconf']['uri'])) + $uri = $_SESSION['ldapconf']['uri']; + + // If Page called first time, field is empty + if((!isset($uri))||(empty($uri))) + $uri = "ldap://localhost:389"; + + + $smarty = get_smarty(); + + // if isset $uri save it to session + if(isset($uri)) + { + $_SESSION['ldapconf']['uri'] = $uri; + $smarty->assign ("uri", validate($uri)); + } + + + // No error till now + $fault = false; + + + // If we pushed the Button continue + if(isset($_POST['continue3'])) + if(!isset($uri)) + { + $fault = true; + // Output the Error + if($withoutput) + { + print_red (_("You've to specify an ldap server before continuing!")); + $smarty->assign ("content", get_template_path('setup_step3.tpl')); + } + } + elseif (!$ds = @ldap_connect (validate($uri))) + { + $fault =true; + // Output the Error + if($withoutput) + { + print_red (_("Can't connect to the specified LDAP server! Please make sure that is reachable for GOsa.")); + $smarty->assign ("uri", validate($uri)); + $smarty->assign ("content", get_template_path('setup_step3.tpl')); + } + } + else + { + // Try to bind the connection + ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); + + // if we can't bind , print error + if (!$r = @ldap_bind ($ds)) + { + $fault = true; + // Output the Error + if($withoutput) + { + print_red (_("Can't bind to the specified LDAP server! Please make sure that is reachable for GOsa.")); + $smarty->assign ("content", get_template_path('setup_step3.tpl')); + $smarty->assign ("uri", validate($uri)); + } + } + else + { + $fault = false; + } + } + + + $smarty->assign ("content", get_template_path('setup_step3.tpl')); + + + // Load Header + if($withoutput) + $smarty->display (get_template_path('headers.tpl')); + + // Set Errors to Smarty + if (isset($_SESSION['errors'])) + { + $smarty->assign("errors", $_SESSION['errors']); + } + + // Print out Template + if($withoutput) + $smarty->display (get_template_path('setup.tpl')); + + + + return (!$fault); +} + + + +// Setup page 4 +// This page asked for detailed info, like base dn or admin user +// if evrything is ok , but there's a missing user with ACL :all we show a a user creation page before we show page 5 +function show_setup_page4($withoutput = true) +{ + + + require_once("class_password-methods.inc"); + + error_reporting(E_ALL); + + + + + $fault = false; // If an error occures we set this var to true + $smarty = get_smarty(); // Our smarty instance + $uri = $_SESSION['ldapconf']['uri']; // This is the the connect path to the ldapserver like ldap://lo.. + $ldapconf = $_SESSION['ldapconf']; // The ldap Configuration informations, we collected while setup + $arr_crypts = array(); // array which includes contains all possible password crypting methods + $temp = ""; // Temp + $checkvars = array("location","admin","password","peopleou","peopledn","arr_crypts","mail","uidbase"); + + + if(!isset($_SESSION['ldapconf']['arr_cryptkeys'])) + { + require_once("class_password-methods.inc"); + $tmp = passwordMethod::get_available_methods_if_not_loaded(); + $_SESSION['ldapconf']['arr_cryptkeys']= $tmp['name']; + } + + + + if(!isset($_SESSION['ldapconf']['mail_methods'])) + { + $_SESSION['ldapconf']['mail_methods']=array(); + $temp = get_available_mail_classes(); + $_SESSION['ldapconf']['mail_methods']= $temp['name']; + } + + + + + // If there are some empty vars in ldapconnect + // This values also represent out default values + +# first try to get $base + if(!$ds = ldap_connect (validate($uri))) + { + $fault = true; + } + elseif(!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) + { + $fault = true; + } + elseif(! $r = ldap_bind ($ds)) + { + $fault = true; + } + else + { + $sr= ldap_search ($ds, "", "objectClass=*", array("namingContexts")); + + + $attr= ldap_get_entries($ds,$sr); + if((empty($attr))) + { + $base= "dc=example,dc=net"; + + + if($withoutput) + print_red(_("Bind to server successfull, but the server seems to be completly empty, please check all informations twice")); + + } + else + { + $base= $attr[0]['dn']; + } + } + + + + if(!isset($_SESSION['ldapconf']['base'])) $_SESSION['ldapconf']['base'] = $base; + if(!isset($_SESSION['ldapconf']['admin'])) $_SESSION['ldapconf']['admin'] = "cn=ldapadmin,".$base; + if(!isset($_SESSION['ldapconf']['peopleou'])) $_SESSION['ldapconf']['peopleou'] = "ou=people"; + if(!isset($_SESSION['ldapconf']['groupou'])) $_SESSION['ldapconf']['groupou'] = "ou=groups"; + if(!isset($_SESSION['ldapconf']['peopledn'])) $_SESSION['ldapconf']['peopledn'] = "cn"; + if(!isset($_SESSION['ldapconf']['password'])) $_SESSION['ldapconf']['password'] = ""; + if(!isset($_SESSION['ldapconf']['location'])) $_SESSION['ldapconf']['location'] = "Example"; + if(!isset($_SESSION['ldapconf']['uidbase'])) $_SESSION['ldapconf']['uidbase'] = "1000"; + if(!isset($_SESSION['ldapconf']['mail'])) $_SESSION['ldapconf']['mail'] = 0; + $tmp = array_flip($_SESSION['ldapconf']['arr_cryptkeys']); + if(!isset($_SESSION['ldapconf']['arr_crypts'])) $_SESSION['ldapconf']['arr_crypts'] = $tmp['md5']; + + + // check Post data + + if(isset($_POST['check'])) + { + // Check if all needed vars are submitted + foreach($checkvars as $key) + { + if((isset($_POST[$key]))&&($_POST[$key]!="")) + { + $_SESSION['ldapconf'][$key] = $_POST[$key]; + } + else + { + if($withoutput) + { + print_red(sprintf(_("You're missing the required attribute '%s' from this formular. Please complete!"), $key)); + } + $fault = true; + } + } + + // check if another base is given ... (ldapadmin...dc=base,dc=de) .. + + $base = $_SESSION['ldapconf']['admin']; + $tmp = array_reverse ( split(",",$base)); + $base = $tmp[1].",".$tmp[0]; + $_SESSION['ldapconf']['base'] = $base; + + + } + + + + $smarty->assign("arr_cryptkeys",$_SESSION['ldapconf']['arr_cryptkeys']); + $smarty->assign("mail_methods", $_SESSION['ldapconf']['mail_methods']); + + foreach($_SESSION['ldapconf'] as $key => $val) + { + $smarty->assign($key,$val); + } + + if(isset($_POST['check'])) + { + $ldap= new LDAP($_SESSION['ldapconf']['admin'], $_SESSION['ldapconf']['password'], $_SESSION['ldapconf']['uri']); + + $m= schema_check($_SESSION['ldapconf']['uri'], $_SESSION['ldapconf']['admin'], $_SESSION['ldapconf']['password']); + $_SESSION['classes']= $m; + + + if ($ldap->error != "Success") + { + if($withoutput) + { + print_red(sprintf(_("Can't log into LDAP server. Reason was: %s."), $ldap->get_error())); + } + $fault = true; + } + } + + + + // Set smarty output + $smarty->assign ("content", get_template_path('setup_step4.tpl')); + + $smarty->assign ("peopledns", array("cn", "uid")); + if($withoutput) + $smarty->display (get_template_path('headers.tpl')); + + if(isset($_SESSION['errors'])) + { + $smarty->assign("errors", $_SESSION['errors']); + } + if($withoutput) + $smarty->display (get_template_path('setup.tpl')); + + + return (!$fault); + + +} + + + + +// This page shows your configuration +// and wants you to download the gosa.conf .... +function show_setup_page5($withoutput=true) +{ + + // Get ldapconf + $ldapconf= $_SESSION['ldapconf']; + + // get smarty + $smarty = get_smarty(); + + $classes = $_SESSION['classes']; + + $info= posix_getgrgid(posix_getgid()); + $smarty->assign ("webgroup", $info['name']); + $smarty->assign ("path", CONFIG_DIR); + $message = ""; + $message.=""; + $m= schema_check($ldapconf['uri'], $ldapconf['admin'], $ldapconf['password'],1); + + if($withoutput) + { + $smarty->assign ("schemas", view_schema_check($m)); + $smarty->assign ("content", get_template_path('setup_finish.tpl')); + } + // Output templates .... + + if($withoutput) + $smarty->display (get_template_path('headers.tpl')); + + if (isset($_SESSION['errors'])) + { + $smarty->assign("errors", $_SESSION['errors']); + } + if($withoutput) + $smarty->display (get_template_path('setup.tpl')); + return(true); +} + + + + + + + + + + + + +// this function is called by setup step 5, in order to create a missinf Administrator +// and or Administrational user +// on success go on with setup_page5 +// else show this page aggain +function create_user_for_setup($withoutput=true) +{ + + error_reporting(E_ALL); + + global $samba; + + $ldapconf = $_SESSION['ldapconf']; + $smarty = get_smarty(); + + $classes= $_SESSION['classes']; + + // Everything runns perfect ... + // So we do a last test on this page + // is there a user with ACLs :all which will be able to adminsitrate GOsa + // We check that, if this user or group is missing we ask for creating them + + $ldap= new LDAP($_SESSION['ldapconf']['admin'], $_SESSION['ldapconf']['password'], $_SESSION['ldapconf']['uri']); + + // $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']); + + // Now we are testing for a group, with the rights :all + $ldap->cd($ldapconf['base']); + $ldap->search("(&(objectClass=gosaObject)(gosaSubtreeACL=:all))"); + + $group_cnt = $ldap->count(); + $data = $ldap->fetch(); + $create_user = false; + + // We need to create Administrative user and group + // Because theres no Group found + if($group_cnt < 1) + { + // Set var to create user + $create_user = true; + + // Output error + if(($withoutput)&&(!isset($_POST['new_admin']))) + print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!")); + } + else + { + + // We found an Administrative Group, is there a user too + if(isset($data['memberUid'][0])) + { + $ldap->search("(&(objectClass=gosaAccount)(objectClass=person))",array("uid=".$data['memberUid'][0])); + $data2 = $ldap->fetch(); + $user_cnt = $ldap->count(); + } + + // We must create a user + if (($ldap->count() < 1)||(!isset($data2))) + { + $create_user = true; + if(($withoutput)&&(!isset($_POST['new_admin']))) + print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!")); + } + else + { + // We don't need to add a user + return(true); + } + + }// if($group_cn) + + // We need to create a new user with group + if(isset($_POST['new_admin'])) + { + // Is there a running user ? + // Then add additional + + if (isset($classes['samba3'])) + { + $samba= "2"; + $lmPassword = "lmPassword"; + $ntPassword = "ntPassword"; + } else { + $samba= "3"; + $lmPassword = "sambaLMPassword"; + $ntPassword = "sambaNtPassword"; + } + + + // Nothing submitted + if(( (empty($_POST['admin_name']))||(empty($_POST['admin_pass'])) )&&(!$create_user)) + { + return(true); + } + + // We have the order to create on Admin ^^ + // Detect Samba version to define the Attribute names shown below + // go to base + $ldap->cd($ldapconf['base']); + + // Define the user we are going to create + $dn = "cn=".$_POST['admin_name'].",".$ldapconf['peopleou'].",".$ldapconf['base']; + + + $arr['objectClass'][0] ="person"; + $arr['objectClass'][1] ="organizationalPerson"; + $arr['objectClass'][2] ="inetOrgPerson"; + $arr['objectClass'][3] ="gosaAccount"; + $arr['uid'] = $_POST['admin_name']; + $arr['cn'] = $_POST['admin_name']; + $arr['sn'] = $_POST['admin_name']; + + $arr['givenName'] = "GOsa main administrator"; + $arr[$lmPassword] = "10974C6EFC0AEE1917306D272A9441BB"; + $arr[$ntPassword] = "38F3951141D0F71A039CFA9D1EC06378"; + $arr['userPassword'] = crypt_single($_POST['admin_pass'],"md5"); + if( ! $ldap->dn_exists ( $dn )) { + $ldap->cd($dn); + $ldap->create_missing_trees($dn); + $ldap->add($arr); + if($ldap->error!="Success") { + print_red("Can't create user, and / or Group, possibly this problem depends on an empty LDAP server. Check your configuration and try again!"); + } + } + + // theres already a group for administrator, so we only need to add the user + if($group_cnt) + { + if(!isset($data['memberUid'])) + { + $arrr['memberUid']= $_POST['admin_name']; + } + else + { + $data['memberUid'][$data['memberUid']['count']]=$_POST['admin_name']; + $arrr['memberUid'] = $data['memberUid']; + unset($arrr['memberUid']['count']); + } + $ldap->cd($data['dn']); + $ldap->modify($arrr); + } + else + { + // there was no group defined, so we must create one + $dn = "cn=administrators,".$ldapconf['groupou'].",".$ldapconf['base']; + $arrr['objectClass'][0] = "gosaObject"; + $arrr['objectClass'][1] = "posixGroup"; + $arrr['gosaSubtreeACL'] = ":all"; + $arrr['cn'] = "administrators"; + $arrr['gidNumber'] = "999"; + $arrr['memberUid'] = $_POST['admin_name']; + $ldap->cd($dn); + $ldap->add($arrr); + } + + + // We created the Group and the user, so we can go on with the next setup step + return(true); + } + else + { + if(!($create_user)) + { + $smarty->assign ("content", get_template_path('setup_useradmin.tpl')); + $smarty->assign("exists",true); + } + else + { + $smarty->assign ("content", get_template_path('setup_useradmin.tpl')); + $smarty->assign("exists",false); + } + } + + + // Smarty outout + + if($withoutput) + $smarty->display (get_template_path('headers.tpl')); + + if (isset($_SESSION['errors'])) + { + $smarty->assign("errors", $_SESSION['errors']); + } + if($withoutput) + $smarty->display (get_template_path('setup.tpl')); + + + return(false); +} + + +// Returns the classnames auf the mail classes +function get_available_mail_classes() +{ + $dir = opendir( "../include"); + $methods = array(); + $suffix = "class_mail-methods-"; + $lensuf = strlen($suffix); + $prefix = ".inc"; + $lenpre = strlen($prefix); + + + $i = 0; + while (($file = readdir($dir)) !== false) + { + if(stristr($file,$suffix)) + { + $lenfile = strlen($file); + $methods['name'][$i] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre); + $methods['file'][$i] = $file; + $methods[$i]['file'] = $file; + $methods[$i]['name'] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre); + $i++; + } + } + return($methods); +} + + + + + + + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/include/smarty/Config_File.class.php b/include/smarty/Config_File.class.php new file mode 100644 index 000000000..b5fdd2269 --- /dev/null +++ b/include/smarty/Config_File.class.php @@ -0,0 +1,389 @@ + + * @access public + * @package Smarty + */ + +/* $Id: Config_File.class.php,v 1.78 2005/03/22 08:45:06 messju Exp $ */ + +/** + * Config file reading class + * @package Smarty + */ +class Config_File { + /**#@+ + * Options + * @var boolean + */ + /** + * Controls whether variables with the same name overwrite each other. + */ + var $overwrite = true; + + /** + * Controls whether config values of on/true/yes and off/false/no get + * converted to boolean values automatically. + */ + var $booleanize = true; + + /** + * Controls whether hidden config sections/vars are read from the file. + */ + var $read_hidden = true; + + /** + * Controls whether or not to fix mac or dos formatted newlines. + * If set to true, \r or \r\n will be changed to \n. + */ + var $fix_newlines = true; + /**#@-*/ + + /** @access private */ + var $_config_path = ""; + var $_config_data = array(); + /**#@-*/ + + /** + * Constructs a new config file class. + * + * @param string $config_path (optional) path to the config files + */ + function Config_File($config_path = NULL) + { + if (isset($config_path)) + $this->set_path($config_path); + } + + + /** + * Set the path where configuration files can be found. + * + * @param string $config_path path to the config files + */ + function set_path($config_path) + { + if (!empty($config_path)) { + if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) { + $this->_trigger_error_msg("Bad config file path '$config_path'"); + return; + } + if(substr($config_path, -1) != DIRECTORY_SEPARATOR) { + $config_path .= DIRECTORY_SEPARATOR; + } + + $this->_config_path = $config_path; + } + } + + + /** + * Retrieves config info based on the file, section, and variable name. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @param string $var_name (optional) variable to get info for + * @return string|array a value or array of values + */ + function &get($file_name, $section_name = NULL, $var_name = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) + $this->load_file($file_name, false); + } + + if (!empty($var_name)) { + if (empty($section_name)) { + return $this->_config_data[$file_name]["vars"][$var_name]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name])) + return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]; + else + return array(); + } + } else { + if (empty($section_name)) { + return (array)$this->_config_data[$file_name]["vars"]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"])) + return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"]; + else + return array(); + } + } + } + + + /** + * Retrieves config info based on the key. + * + * @param $file_name string config key (filename/section/var) + * @return string|array same as get() + * @uses get() retrieves information from config file and returns it + */ + function &get_key($config_key) + { + list($file_name, $section_name, $var_name) = explode('/', $config_key, 3); + $result = &$this->get($file_name, $section_name, $var_name); + return $result; + } + + /** + * Get all loaded config file names. + * + * @return array an array of loaded config file names + */ + function get_file_names() + { + return array_keys($this->_config_data); + } + + + /** + * Get all section names from a loaded file. + * + * @param string $file_name config file to get section names from + * @return array an array of section names from the specified file + */ + function get_section_names($file_name) + { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + return array_keys($this->_config_data[$file_name]["sections"]); + } + + + /** + * Get all global or section variable names. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @return array an array of variables names from the specified file/section + */ + function get_var_names($file_name, $section = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + if (empty($section)) + return array_keys($this->_config_data[$file_name]["vars"]); + else + return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]); + } + + + /** + * Clear loaded config data for a certain file or all files. + * + * @param string $file_name file to clear config data for + */ + function clear($file_name = NULL) + { + if ($file_name === NULL) + $this->_config_data = array(); + else if (isset($this->_config_data[$file_name])) + $this->_config_data[$file_name] = array(); + } + + + /** + * Load a configuration file manually. + * + * @param string $file_name file name to load + * @param boolean $prepend_path whether current config path should be + * prepended to the filename + */ + function load_file($file_name, $prepend_path = true) + { + if ($prepend_path && $this->_config_path != "") + $config_file = $this->_config_path . $file_name; + else + $config_file = $file_name; + + ini_set('track_errors', true); + $fp = @fopen($config_file, "r"); + if (!is_resource($fp)) { + $this->_trigger_error_msg("Could not open config file '$config_file'"); + return false; + } + + $contents = ($size = filesize($config_file)) ? fread($fp, $size) : ''; + fclose($fp); + + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * Store the contents of a file manually. + * + * @param string $config_file file name of the related contents + * @param string $contents the file-contents to parse + */ + function set_file_contents($config_file, $contents) + { + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * parse the source of a configuration file manually. + * + * @param string $contents the file-contents to parse + */ + function parse_contents($contents) + { + if($this->fix_newlines) { + // fix mac/dos formatted newlines + $contents = preg_replace('!\r\n?!', "\n", $contents); + } + + $config_data = array(); + $config_data['sections'] = array(); + $config_data['vars'] = array(); + + /* reference to fill with data */ + $vars =& $config_data['vars']; + + /* parse file line by line */ + preg_match_all('!^.*\r?\n?!m', $contents, $match); + $lines = $match[0]; + for ($i=0, $count=count($lines); $i<$count; $i++) { + $line = $lines[$i]; + if (empty($line)) continue; + + if ( $line{0} == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) { + /* section found */ + if ($match[1]{0} == '.') { + /* hidden section */ + if ($this->read_hidden) { + $section_name = substr($match[1], 1); + } else { + /* break reference to $vars to ignore hidden section */ + unset($vars); + $vars = array(); + continue; + } + } else { + $section_name = $match[1]; + } + if (!isset($config_data['sections'][$section_name])) + $config_data['sections'][$section_name] = array('vars' => array()); + $vars =& $config_data['sections'][$section_name]['vars']; + continue; + } + + if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) { + /* variable found */ + $var_name = rtrim($match[1]); + if (strpos($match[2], '"""') === 0) { + /* handle multiline-value */ + $lines[$i] = substr($match[2], 3); + $var_value = ''; + while ($i<$count) { + if (($pos = strpos($lines[$i], '"""')) === false) { + $var_value .= $lines[$i++]; + } else { + /* end of multiline-value */ + $var_value .= substr($lines[$i], 0, $pos); + break; + } + } + $booleanize = false; + + } else { + /* handle simple value */ + $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2])); + $booleanize = $this->booleanize; + + } + $this->_set_config_var($vars, $var_name, $var_value, $booleanize); + } + /* else unparsable line / means it is a comment / means ignore it */ + } + return $config_data; + } + + /**#@+ @access private */ + /** + * @param array &$container + * @param string $var_name + * @param mixed $var_value + * @param boolean $booleanize determines whether $var_value is converted to + * to true/false + */ + function _set_config_var(&$container, $var_name, $var_value, $booleanize) + { + if ($var_name{0} == '.') { + if (!$this->read_hidden) + return; + else + $var_name = substr($var_name, 1); + } + + if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) { + $this->_trigger_error_msg("Bad variable name '$var_name'"); + return; + } + + if ($booleanize) { + if (preg_match("/^(on|true|yes)$/i", $var_value)) + $var_value = true; + else if (preg_match("/^(off|false|no)$/i", $var_value)) + $var_value = false; + } + + if (!isset($container[$var_name]) || $this->overwrite) + $container[$var_name] = $var_value; + else { + settype($container[$var_name], 'array'); + $container[$var_name][] = $var_value; + } + } + + /** + * @uses trigger_error() creates a PHP warning/error + * @param string $error_msg + * @param integer $error_type one of + */ + function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Config_File error: $error_msg", $error_type); + } + /**#@-*/ +} + +?> diff --git a/include/smarty/Smarty.class.php b/include/smarty/Smarty.class.php new file mode 100644 index 000000000..bb5129007 --- /dev/null +++ b/include/smarty/Smarty.class.php @@ -0,0 +1,1934 @@ + + * @author Andrei Zmievski + * @package Smarty + * @version 2.6.9 + */ + +/* $Id: Smarty.class.php,v 1.514 2005/03/22 08:45:06 messju Exp $ */ + +/** + * DIR_SEP isn't used anymore, but third party apps might + */ +if(!defined('DIR_SEP')) { + define('DIR_SEP', DIRECTORY_SEPARATOR); +} + +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * if not defined, include_path will be used. Sets SMARTY_DIR only if user + * application has not already defined it. + */ + +if (!defined('SMARTY_DIR')) { + define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} + +if (!defined('SMARTY_CORE_DIR')) { + define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR); +} + +define('SMARTY_PHP_PASSTHRU', 0); +define('SMARTY_PHP_QUOTE', 1); +define('SMARTY_PHP_REMOVE', 2); +define('SMARTY_PHP_ALLOW', 3); + +/** + * @package Smarty + */ +class Smarty +{ + /**#@+ + * Smarty Configuration Section + */ + + /** + * The name of the directory where templates are located. + * + * @var string + */ + var $template_dir = 'templates'; + + /** + * The directory where compiled templates are located. + * + * @var string + */ + var $compile_dir = 'templates_c'; + + /** + * The directory where config files are located. + * + * @var string + */ + var $config_dir = 'configs'; + + /** + * An array of directories searched for plugins. + * + * @var array + */ + var $plugins_dir = array('plugins'); + + /** + * If debugging is enabled, a debug console window will display + * when the page loads (make sure your browser allows unrequested + * popup windows) + * + * @var boolean + */ + var $debugging = false; + + /** + * When set, smarty does uses this value as error_reporting-level. + * + * @var boolean + */ + var $error_reporting = null; + + /** + * This is the path to the debug console template. If not set, + * the default one will be used. + * + * @var string + */ + var $debug_tpl = ''; + + /** + * This determines if debugging is enable-able from the browser. + *
    + *
  • NONE => no debugging control allowed
  • + *
  • URL => enable debugging when SMARTY_DEBUG is found in the URL.
  • + *
+ * @link http://www.foo.dom/index.php?SMARTY_DEBUG + * @var string + */ + var $debugging_ctrl = 'NONE'; + + /** + * This tells Smarty whether to check for recompiling or not. Recompiling + * does not need to happen unless a template or config file is changed. + * Typically you enable this during development, and disable for + * production. + * + * @var boolean + */ + var $compile_check = true; + + /** + * This forces templates to compile every time. Useful for development + * or debugging. + * + * @var boolean + */ + var $force_compile = false; + + /** + * This enables template caching. + *
    + *
  • 0 = no caching
  • + *
  • 1 = use class cache_lifetime value
  • + *
  • 2 = use cache_lifetime in cache file
  • + *
+ * @var integer + */ + var $caching = 0; + + /** + * The name of the directory for cache files. + * + * @var string + */ + var $cache_dir = 'cache'; + + /** + * This is the number of seconds cached content will persist. + *
    + *
  • 0 = always regenerate cache
  • + *
  • -1 = never expires
  • + *
+ * + * @var integer + */ + var $cache_lifetime = 3600; + + /** + * Only used when $caching is enabled. If true, then If-Modified-Since headers + * are respected with cached content, and appropriate HTTP headers are sent. + * This way repeated hits to a cached page do not send the entire page to the + * client every time. + * + * @var boolean + */ + var $cache_modified_check = false; + + /** + * This determines how Smarty handles "" tags in templates. + * possible values: + *
    + *
  • SMARTY_PHP_PASSTHRU -> print tags as plain text
  • + *
  • SMARTY_PHP_QUOTE -> escape tags as entities
  • + *
  • SMARTY_PHP_REMOVE -> remove php tags
  • + *
  • SMARTY_PHP_ALLOW -> execute php tags
  • + *
+ * + * @var integer + */ + var $php_handling = SMARTY_PHP_PASSTHRU; + + /** + * This enables template security. When enabled, many things are restricted + * in the templates that normally would go unchecked. This is useful when + * untrusted parties are editing templates and you want a reasonable level + * of security. (no direct execution of PHP in templates for example) + * + * @var boolean + */ + var $security = false; + + /** + * This is the list of template directories that are considered secure. This + * is used only if {@link $security} is enabled. One directory per array + * element. {@link $template_dir} is in this list implicitly. + * + * @var array + */ + var $secure_dir = array(); + + /** + * These are the security settings for Smarty. They are used only when + * {@link $security} is enabled. + * + * @var array + */ + var $security_settings = array( + 'PHP_HANDLING' => false, + 'IF_FUNCS' => array('array', 'list', + 'isset', 'empty', + 'count', 'sizeof', + 'in_array', 'is_array', + 'true', 'false', 'null'), + 'INCLUDE_ANY' => false, + 'PHP_TAGS' => false, + 'MODIFIER_FUNCS' => array('count'), + 'ALLOW_CONSTANTS' => false + ); + + /** + * This is an array of directories where trusted php scripts reside. + * {@link $security} is disabled during their inclusion/execution. + * + * @var array + */ + var $trusted_dir = array(); + + /** + * The left delimiter used for the template tags. + * + * @var string + */ + var $left_delimiter = '{'; + + /** + * The right delimiter used for the template tags. + * + * @var string + */ + var $right_delimiter = '}'; + + /** + * The order in which request variables are registered, similar to + * variables_order in php.ini E = Environment, G = GET, P = POST, + * C = Cookies, S = Server + * + * @var string + */ + var $request_vars_order = 'EGPCS'; + + /** + * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false) + * are uses as request-vars or $_*[]-vars. note: if + * request_use_auto_globals is true, then $request_vars_order has + * no effect, but the php-ini-value "gpc_order" + * + * @var boolean + */ + var $request_use_auto_globals = true; + + /** + * Set this if you want different sets of compiled files for the same + * templates. This is useful for things like different languages. + * Instead of creating separate sets of templates per language, you + * set different compile_ids like 'en' and 'de'. + * + * @var string + */ + var $compile_id = null; + + /** + * This tells Smarty whether or not to use sub dirs in the cache/ and + * templates_c/ directories. sub directories better organized, but + * may not work well with PHP safe mode enabled. + * + * @var boolean + * + */ + var $use_sub_dirs = false; + + /** + * This is a list of the modifiers to apply to all template variables. + * Put each modifier in a separate array element in the order you want + * them applied. example: array('escape:"htmlall"'); + * + * @var array + */ + var $default_modifiers = array(); + + /** + * This is the resource type to be used when not specified + * at the beginning of the resource path. examples: + * $smarty->display('file:index.tpl'); + * $smarty->display('db:index.tpl'); + * $smarty->display('index.tpl'); // will use default resource type + * {include file="file:index.tpl"} + * {include file="db:index.tpl"} + * {include file="index.tpl"} {* will use default resource type *} + * + * @var array + */ + var $default_resource_type = 'file'; + + /** + * The function used for cache file handling. If not set, built-in caching is used. + * + * @var null|string function name + */ + var $cache_handler_func = null; + + /** + * This indicates which filters are automatically loaded into Smarty. + * + * @var array array of filter names + */ + var $autoload_filters = array(); + + /**#@+ + * @var boolean + */ + /** + * This tells if config file vars of the same name overwrite each other or not. + * if disabled, same name variables are accumulated in an array. + */ + var $config_overwrite = true; + + /** + * This tells whether or not to automatically booleanize config file variables. + * If enabled, then the strings "on", "true", and "yes" are treated as boolean + * true, and "off", "false" and "no" are treated as boolean false. + */ + var $config_booleanize = true; + + /** + * This tells whether hidden sections [.foobar] are readable from the + * tempalates or not. Normally you would never allow this since that is + * the point behind hidden sections: the application can access them, but + * the templates cannot. + */ + var $config_read_hidden = false; + + /** + * This tells whether or not automatically fix newlines in config files. + * It basically converts \r (mac) or \r\n (dos) to \n + */ + var $config_fix_newlines = true; + /**#@-*/ + + /** + * If a template cannot be found, this PHP function will be executed. + * Useful for creating templates on-the-fly or other special action. + * + * @var string function name + */ + var $default_template_handler_func = ''; + + /** + * The file that contains the compiler class. This can a full + * pathname, or relative to the php_include path. + * + * @var string + */ + var $compiler_file = 'Smarty_Compiler.class.php'; + + /** + * The class used for compiling templates. + * + * @var string + */ + var $compiler_class = 'Smarty_Compiler'; + + /** + * The class used to load config vars. + * + * @var string + */ + var $config_class = 'Config_File'; + +/**#@+ + * END Smarty Configuration Section + * There should be no need to touch anything below this line. + * @access private + */ + /** + * where assigned template vars are kept + * + * @var array + */ + var $_tpl_vars = array(); + + /** + * stores run-time $smarty.* vars + * + * @var null|array + */ + var $_smarty_vars = null; + + /** + * keeps track of sections + * + * @var array + */ + var $_sections = array(); + + /** + * keeps track of foreach blocks + * + * @var array + */ + var $_foreach = array(); + + /** + * keeps track of tag hierarchy + * + * @var array + */ + var $_tag_stack = array(); + + /** + * configuration object + * + * @var Config_file + */ + var $_conf_obj = null; + + /** + * loaded configuration settings + * + * @var array + */ + var $_config = array(array('vars' => array(), 'files' => array())); + + /** + * md5 checksum of the string 'Smarty' + * + * @var string + */ + var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; + + /** + * Smarty version number + * + * @var string + */ + var $_version = '2.6.9'; + + /** + * current template inclusion depth + * + * @var integer + */ + var $_inclusion_depth = 0; + + /** + * for different compiled templates + * + * @var string + */ + var $_compile_id = null; + + /** + * text in URL to enable debug mode + * + * @var string + */ + var $_smarty_debug_id = 'SMARTY_DEBUG'; + + /** + * debugging information for debug console + * + * @var array + */ + var $_smarty_debug_info = array(); + + /** + * info that makes up a cache file + * + * @var array + */ + var $_cache_info = array(); + + /** + * default file permissions + * + * @var integer + */ + var $_file_perms = 0644; + + /** + * default dir permissions + * + * @var integer + */ + var $_dir_perms = 0771; + + /** + * registered objects + * + * @var array + */ + var $_reg_objects = array(); + + /** + * table keeping track of plugins + * + * @var array + */ + var $_plugins = array( + 'modifier' => array(), + 'function' => array(), + 'block' => array(), + 'compiler' => array(), + 'prefilter' => array(), + 'postfilter' => array(), + 'outputfilter' => array(), + 'resource' => array(), + 'insert' => array()); + + + /** + * cache serials + * + * @var array + */ + var $_cache_serials = array(); + + /** + * name of optional cache include file + * + * @var string + */ + var $_cache_include = null; + + /** + * indicate if the current code is used in a compiled + * include + * + * @var string + */ + var $_cache_including = false; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty() + { + $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] + : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']); + } + + /** + * assigns values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to assign + */ + function assign($tpl_var, $value = null) + { + if (is_array($tpl_var)){ + foreach ($tpl_var as $key => $val) { + if ($key != '') { + $this->_tpl_vars[$key] = $val; + } + } + } else { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = $value; + } + } + + /** + * assigns values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to assign + */ + function assign_by_ref($tpl_var, &$value) + { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = &$value; + } + + /** + * appends values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to append + */ + function append($tpl_var, $value=null, $merge=false) + { + if (is_array($tpl_var)) { + // $tpl_var is an array, ignore $value + foreach ($tpl_var as $_key => $_val) { + if ($_key != '') { + if(!@is_array($this->_tpl_vars[$_key])) { + settype($this->_tpl_vars[$_key],'array'); + } + if($merge && is_array($_val)) { + foreach($_val as $_mkey => $_mval) { + $this->_tpl_vars[$_key][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$_key][] = $_val; + } + } + } + } else { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if($merge && is_array($value)) { + foreach($value as $_mkey => $_mval) { + $this->_tpl_vars[$tpl_var][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$tpl_var][] = $value; + } + } + } + } + + /** + * appends values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to append + */ + function append_by_ref($tpl_var, &$value, $merge=false) + { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if ($merge && is_array($value)) { + foreach($value as $_key => $_val) { + $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key]; + } + } else { + $this->_tpl_vars[$tpl_var][] = &$value; + } + } + } + + + /** + * clear the given assigned template variable. + * + * @param string $tpl_var the template variable to clear + */ + function clear_assign($tpl_var) + { + if (is_array($tpl_var)) + foreach ($tpl_var as $curr_var) + unset($this->_tpl_vars[$curr_var]); + else + unset($this->_tpl_vars[$tpl_var]); + } + + + /** + * Registers custom function to be used in templates + * + * @param string $function the name of the template function + * @param string $function_impl the name of the PHP function to register + */ + function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['function'][$function] = + array($function_impl, null, null, false, $cacheable, $cache_attrs); + + } + + /** + * Unregisters custom function + * + * @param string $function name of template function + */ + function unregister_function($function) + { + unset($this->_plugins['function'][$function]); + } + + /** + * Registers object to be used in templates + * + * @param string $object name of template object + * @param object &$object_impl the referenced PHP object to register + * @param null|array $allowed list of allowed methods (empty = all) + * @param boolean $smarty_args smarty argument format, else traditional + * @param null|array $block_functs list of methods that are block format + */ + function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + { + settype($allowed, 'array'); + settype($smarty_args, 'boolean'); + $this->_reg_objects[$object] = + array(&$object_impl, $allowed, $smarty_args, $block_methods); + } + + /** + * Unregisters object + * + * @param string $object name of template object + */ + function unregister_object($object) + { + unset($this->_reg_objects[$object]); + } + + + /** + * Registers block function to be used in templates + * + * @param string $block name of template block + * @param string $block_impl PHP function to register + */ + function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['block'][$block] = + array($block_impl, null, null, false, $cacheable, $cache_attrs); + } + + /** + * Unregisters block function + * + * @param string $block name of template function + */ + function unregister_block($block) + { + unset($this->_plugins['block'][$block]); + } + + /** + * Registers compiler function + * + * @param string $function name of template function + * @param string $function_impl name of PHP function to register + */ + function register_compiler_function($function, $function_impl, $cacheable=true) + { + $this->_plugins['compiler'][$function] = + array($function_impl, null, null, false, $cacheable); + } + + /** + * Unregisters compiler function + * + * @param string $function name of template function + */ + function unregister_compiler_function($function) + { + unset($this->_plugins['compiler'][$function]); + } + + /** + * Registers modifier to be used in templates + * + * @param string $modifier name of template modifier + * @param string $modifier_impl name of PHP function to register + */ + function register_modifier($modifier, $modifier_impl) + { + $this->_plugins['modifier'][$modifier] = + array($modifier_impl, null, null, false); + } + + /** + * Unregisters modifier + * + * @param string $modifier name of template modifier + */ + function unregister_modifier($modifier) + { + unset($this->_plugins['modifier'][$modifier]); + } + + /** + * Registers a resource to fetch a template + * + * @param string $type name of resource + * @param array $functions array of functions to handle resource + */ + function register_resource($type, $functions) + { + if (count($functions)==4) { + $this->_plugins['resource'][$type] = + array($functions, false); + + } elseif (count($functions)==5) { + $this->_plugins['resource'][$type] = + array(array(array(&$functions[0], $functions[1]) + ,array(&$functions[0], $functions[2]) + ,array(&$functions[0], $functions[3]) + ,array(&$functions[0], $functions[4])) + ,false); + + } else { + $this->trigger_error("malformed function-list for '$type' in register_resource"); + + } + } + + /** + * Unregisters a resource + * + * @param string $type name of resource + */ + function unregister_resource($type) + { + unset($this->_plugins['resource'][$type]); + } + + /** + * Registers a prefilter function to apply + * to a template before compiling + * + * @param string $function name of PHP function to register + */ + function register_prefilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['prefilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a prefilter function + * + * @param string $function name of PHP function + */ + function unregister_prefilter($function) + { + unset($this->_plugins['prefilter'][$function]); + } + + /** + * Registers a postfilter function to apply + * to a compiled template after compilation + * + * @param string $function name of PHP function to register + */ + function register_postfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['postfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a postfilter function + * + * @param string $function name of PHP function + */ + function unregister_postfilter($function) + { + unset($this->_plugins['postfilter'][$function]); + } + + /** + * Registers an output filter function to apply + * to a template output + * + * @param string $function name of PHP function + */ + function register_outputfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['outputfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters an outputfilter function + * + * @param string $function name of PHP function + */ + function unregister_outputfilter($function) + { + unset($this->_plugins['outputfilter'][$function]); + } + + /** + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + */ + function load_filter($type, $name) + { + switch ($type) { + case 'output': + $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + break; + + case 'pre': + case 'post': + if (!isset($this->_plugins[$type . 'filter'][$name])) + $this->_plugins[$type . 'filter'][$name] = false; + break; + } + } + + /** + * clear cached content for the given template and cache id + * + * @param string $tpl_file name of template file + * @param string $cache_id name of cache_id + * @param string $compile_id name of compile_id + * @param string $exp_time expiration time + * @return boolean + */ + function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + if (!isset($tpl_file)) + $compile_id = null; + + $_auto_id = $this->_get_auto_id($cache_id, $compile_id); + + if (!empty($this->cache_handler_func)) { + return call_user_func_array($this->cache_handler_func, + array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time)); + } else { + $_params = array('auto_base' => $this->cache_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $_auto_id, + 'exp_time' => $exp_time); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + } + + + /** + * clear the entire contents of cache (all templates) + * + * @param string $exp_time expire time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_all_cache($exp_time = null) + { + return $this->clear_cache(null, null, null, $exp_time); + } + + + /** + * test to see if valid cache exists for this template + * + * @param string $tpl_file name of template file + * @param string $cache_id + * @param string $compile_id + * @return string|false results of {@link _read_cache_file()} + */ + function is_cached($tpl_file, $cache_id = null, $compile_id = null) + { + if (!$this->caching) + return false; + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + $_params = array( + 'tpl_file' => $tpl_file, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + return smarty_core_read_cache_file($_params, $this); + } + + + /** + * clear all the assigned template variables. + * + */ + function clear_all_assign() + { + $this->_tpl_vars = array(); + } + + /** + * clears compiled version of specified template resource, + * or all compiled template files if one is not specified. + * This function is for advanced use only, not normally needed. + * + * @param string $tpl_file + * @param string $compile_id + * @param string $exp_time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) + { + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + $_params = array('auto_base' => $this->compile_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $compile_id, + 'exp_time' => $exp_time, + 'extensions' => array('.inc', '.php')); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + /** + * Checks whether requested template exists. + * + * @param string $tpl_file + * @return boolean + */ + function template_exists($tpl_file) + { + $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false); + return $this->_fetch_resource_info($_params); + } + + /** + * Returns an array containing template variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_template_vars($name=null) + { + if(!isset($name)) { + return $this->_tpl_vars; + } + if(isset($this->_tpl_vars[$name])) { + return $this->_tpl_vars[$name]; + } + } + + /** + * Returns an array containing config variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_config_vars($name=null) + { + if(!isset($name) && is_array($this->_config[0])) { + return $this->_config[0]['vars']; + } else if(isset($this->_config[0]['vars'][$name])) { + return $this->_config[0]['vars'][$name]; + } + } + + /** + * trigger Smarty error + * + * @param string $error_msg + * @param integer $error_type + */ + function trigger_error($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Smarty error: $error_msg", $error_type); + } + + + /** + * executes & displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + */ + function display($resource_name, $cache_id = null, $compile_id = null) + { + $this->fetch($resource_name, $cache_id, $compile_id, true); + } + + /** + * executes & returns or displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + * @param boolean $display + */ + function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) + { + static $_cache_info = array(); + + $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) + ? $this->error_reporting : error_reporting() & ~E_NOTICE); + + if (!$this->debugging && $this->debugging_ctrl == 'URL') { + $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']; + if (@strstr($_query_string, $this->_smarty_debug_id)) { + if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) { + // enable debugging for this browser session + @setcookie('SMARTY_DEBUG', true); + $this->debugging = true; + } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) { + // disable debugging for this browser session + @setcookie('SMARTY_DEBUG', false); + $this->debugging = false; + } else { + // enable debugging for this page + $this->debugging = true; + } + } else { + $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']); + } + } + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $resource_name, + 'depth' => 0); + $_included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + + $this->_compile_id = $compile_id; + $this->_inclusion_depth = 0; + + if ($this->caching) { + // save old cache_info, initialize cache_info + array_push($_cache_info, $this->_cache_info); + $this->_cache_info = array(); + $_params = array( + 'tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => null + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + if (smarty_core_read_cache_file($_params, $this)) { + $_smarty_results = $_params['results']; + if (!empty($this->_cache_info['insert_tags'])) { + $_params = array('plugins' => $this->_cache_info['insert_tags']); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + } + if (!empty($this->_cache_info['cache_serials'])) { + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php'); + $_smarty_results = smarty_core_process_compiled_include($_params, $this); + } + + + if ($display) { + if ($this->debugging) + { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time; + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + $_smarty_results .= smarty_core_display_debug_console($_params, $this); + } + if ($this->cache_modified_check) { + $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT'; + if (@count($this->_cache_info['insert_tags']) == 0 + && !$this->_cache_serials + && $_gmt_mtime == $_last_modified_date) { + if (php_sapi_name()=='cgi') + header('Status: 304 Not Modified'); + else + header('HTTP/1.1 304 Not Modified'); + + } else { + header('Last-Modified: '.$_gmt_mtime); + echo $_smarty_results; + } + } else { + echo $_smarty_results; + } + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return true; + } else { + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return $_smarty_results; + } + } else { + $this->_cache_info['template'][$resource_name] = true; + if ($this->cache_modified_check && $display) { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT'); + } + } + } + + // load filters that are marked as autoload + if (count($this->autoload_filters)) { + foreach ($this->autoload_filters as $_filter_type => $_filters) { + foreach ($_filters as $_filter) { + $this->load_filter($_filter_type, $_filter); + } + } + } + + $_smarty_compile_path = $this->_get_compile_path($resource_name); + + // if we just need to display the results, don't perform output + // buffering - for speed + $_cache_including = $this->_cache_including; + $this->_cache_including = false; + if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) { + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + } else { + ob_start(); + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + $_smarty_results = ob_get_contents(); + ob_end_clean(); + + foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) { + $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this)); + } + } + + if ($this->caching) { + $_params = array('tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php'); + smarty_core_write_cache_file($_params, $this); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + + if ($this->_cache_serials) { + // strip nocache-tags from output + $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s' + ,'' + ,$_smarty_results); + } + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + } + $this->_cache_including = $_cache_including; + + if ($display) { + if (isset($_smarty_results)) { echo $_smarty_results; } + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time); + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + echo smarty_core_display_debug_console($_params, $this); + } + error_reporting($_smarty_old_error_level); + return; + } else { + error_reporting($_smarty_old_error_level); + if (isset($_smarty_results)) { return $_smarty_results; } + } + } + + /** + * load configuration values + * + * @param string $file + * @param string $section + * @param string $scope + */ + function config_load($file, $section = null, $scope = 'global') + { + require_once($this->_get_plugin_filepath('function', 'config_load')); + smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this); + } + + /** + * return a reference to a registered object + * + * @param string $name + * @return object + */ + function &get_registered_object($name) { + if (!isset($this->_reg_objects[$name])) + $this->_trigger_fatal_error("'$name' is not a registered object"); + + if (!is_object($this->_reg_objects[$name][0])) + $this->_trigger_fatal_error("registered '$name' is not an object"); + + return $this->_reg_objects[$name][0]; + } + + /** + * clear configuration values + * + * @param string $var + */ + function clear_config($var = null) + { + if(!isset($var)) { + // clear all values + $this->_config = array(array('vars' => array(), + 'files' => array())); + } else { + unset($this->_config[0]['vars'][$var]); + } + } + + /** + * get filepath of requested plugin + * + * @param string $type + * @param string $name + * @return string|false + */ + function _get_plugin_filepath($type, $name) + { + $_params = array('type' => $type, 'name' => $name); + require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php'); + return smarty_core_assemble_plugin_filepath($_params, $this); + } + + /** + * test if resource needs compiling + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _is_compiled($resource_name, $compile_path) + { + if (!$this->force_compile && file_exists($compile_path)) { + if (!$this->compile_check) { + // no need to check compiled file + return true; + } else { + // get file source and timestamp + $_params = array('resource_name' => $resource_name, 'get_source'=>false); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + if ($_params['resource_timestamp'] <= filemtime($compile_path)) { + // template not expired, no recompile + return true; + } else { + // compile template + return false; + } + } + } else { + // compiled template does not exist, or forced compile + return false; + } + } + + /** + * compile the template + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _compile_resource($resource_name, $compile_path) + { + + $_params = array('resource_name' => $resource_name); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + + $_source_content = $_params['source_content']; + $_cache_include = substr($compile_path, 0, -4).'.inc'; + + if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) { + // if a _cache_serial was set, we also have to write an include-file: + if ($this->_cache_include_info) { + require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php'); + smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)), $this); + } + + $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $this); + + return true; + } else { + return false; + } + + } + + /** + * compile the given source + * + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return boolean + */ + function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null) + { + if (file_exists(SMARTY_DIR . $this->compiler_file)) { + require_once(SMARTY_DIR . $this->compiler_file); + } else { + // use include_path + require_once($this->compiler_file); + } + + + $smarty_compiler = new $this->compiler_class; + + $smarty_compiler->template_dir = $this->template_dir; + $smarty_compiler->compile_dir = $this->compile_dir; + $smarty_compiler->plugins_dir = $this->plugins_dir; + $smarty_compiler->config_dir = $this->config_dir; + $smarty_compiler->force_compile = $this->force_compile; + $smarty_compiler->caching = $this->caching; + $smarty_compiler->php_handling = $this->php_handling; + $smarty_compiler->left_delimiter = $this->left_delimiter; + $smarty_compiler->right_delimiter = $this->right_delimiter; + $smarty_compiler->_version = $this->_version; + $smarty_compiler->security = $this->security; + $smarty_compiler->secure_dir = $this->secure_dir; + $smarty_compiler->security_settings = $this->security_settings; + $smarty_compiler->trusted_dir = $this->trusted_dir; + $smarty_compiler->use_sub_dirs = $this->use_sub_dirs; + $smarty_compiler->_reg_objects = &$this->_reg_objects; + $smarty_compiler->_plugins = &$this->_plugins; + $smarty_compiler->_tpl_vars = &$this->_tpl_vars; + $smarty_compiler->default_modifiers = $this->default_modifiers; + $smarty_compiler->compile_id = $this->_compile_id; + $smarty_compiler->_config = $this->_config; + $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals; + + if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) { + $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path]; + } + $smarty_compiler->_cache_include = $cache_include_path; + + + $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content); + + if ($smarty_compiler->_cache_serial) { + $this->_cache_include_info = array( + 'cache_serial'=>$smarty_compiler->_cache_serial + ,'plugins_code'=>$smarty_compiler->_plugins_code + ,'include_file_path' => $cache_include_path); + + } else { + $this->_cache_include_info = null; + + } + + return $_results; + } + + /** + * Get the compile path for this resource + * + * @param string $resource_name + * @return string results of {@link _get_auto_filename()} + */ + function _get_compile_path($resource_name) + { + return $this->_get_auto_filename($this->compile_dir, $resource_name, + $this->_compile_id) . '.php'; + } + + /** + * fetch the template info. Gets timestamp, and source + * if get_source is true + * + * sets $source_content to the source of the template, and + * $resource_timestamp to its time stamp + * @param string $resource_name + * @param string $source_content + * @param integer $resource_timestamp + * @param boolean $get_source + * @param boolean $quiet + * @return boolean + */ + + function _fetch_resource_info(&$params) + { + if(!isset($params['get_source'])) { $params['get_source'] = true; } + if(!isset($params['quiet'])) { $params['quiet'] = false; } + + $_return = false; + $_params = array('resource_name' => $params['resource_name']) ; + if (isset($params['resource_base_path'])) + $_params['resource_base_path'] = $params['resource_base_path']; + else + $_params['resource_base_path'] = $this->template_dir; + + if ($this->_parse_resource_name($_params)) { + $_resource_type = $_params['resource_type']; + $_resource_name = $_params['resource_name']; + switch ($_resource_type) { + case 'file': + if ($params['get_source']) { + $params['source_content'] = $this->_read_file($_resource_name); + } + $params['resource_timestamp'] = filemtime($_resource_name); + $_return = is_file($_resource_name); + break; + + default: + // call resource functions to fetch the template source and timestamp + if ($params['get_source']) { + $_source_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][0], + array($_resource_name, &$params['source_content'], &$this)); + } else { + $_source_return = true; + } + + $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][1], + array($_resource_name, &$params['resource_timestamp'], &$this)); + + $_return = $_source_return && $_timestamp_return; + break; + } + } + + if (!$_return) { + // see if we can get a template with the default template handler + if (!empty($this->default_template_handler_func)) { + if (!is_callable($this->default_template_handler_func)) { + $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist."); + } else { + $_return = call_user_func_array( + $this->default_template_handler_func, + array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this)); + } + } + } + + if (!$_return) { + if (!$params['quiet']) { + $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"'); + } + } else if ($_return && $this->security) { + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if (!smarty_core_is_secure($_params, $this)) { + if (!$params['quiet']) + $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed'); + $params['source_content'] = null; + $params['resource_timestamp'] = null; + return false; + } + } + return $_return; + } + + + /** + * parse out the type and name from the resource + * + * @param string $resource_base_path + * @param string $resource_name + * @param string $resource_type + * @param string $resource_name + * @return boolean + */ + + function _parse_resource_name(&$params) + { + + // split tpl_path by the first colon + $_resource_name_parts = explode(':', $params['resource_name'], 2); + + if (count($_resource_name_parts) == 1) { + // no resource type given + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $_resource_name_parts[0]; + } else { + if(strlen($_resource_name_parts[0]) == 1) { + // 1 char is not resource type, but part of filepath + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $params['resource_name']; + } else { + $params['resource_type'] = $_resource_name_parts[0]; + $params['resource_name'] = $_resource_name_parts[1]; + } + } + + if ($params['resource_type'] == 'file') { + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) { + // relative pathname to $params['resource_base_path'] + // use the first directory where the file is found + foreach ((array)$params['resource_base_path'] as $_curr_path) { + $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name']; + if (file_exists($_fullpath) && is_file($_fullpath)) { + $params['resource_name'] = $_fullpath; + return true; + } + // didn't find the file, try include_path + $_params = array('file_path' => $_fullpath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $this)) { + $params['resource_name'] = $_params['new_file_path']; + return true; + } + } + return false; + } else { + /* absolute path */ + return file_exists($params['resource_name']); + } + } elseif (empty($this->_plugins['resource'][$params['resource_type']])) { + $_params = array('type' => $params['resource_type']); + require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php'); + smarty_core_load_resource_plugin($_params, $this); + } + + return true; + } + + + /** + * Handle modifiers + * + * @param string|null $modifier_name + * @param array|null $map_array + * @return string result of modifiers + */ + function _run_mod_handler() + { + $_args = func_get_args(); + list($_modifier_name, $_map_array) = array_splice($_args, 0, 2); + list($_func_name, $_tpl_file, $_tpl_line) = + $this->_plugins['modifier'][$_modifier_name]; + + $_var = $_args[0]; + foreach ($_var as $_key => $_val) { + $_args[0] = $_val; + $_var[$_key] = call_user_func_array($_func_name, $_args); + } + return $_var; + } + + /** + * Remove starting and ending quotes from the string + * + * @param string $string + * @return string + */ + function _dequote($string) + { + if (($string{0} == "'" || $string{0} == '"') && + $string{strlen($string)-1} == $string{0}) + return substr($string, 1, -1); + else + return $string; + } + + + /** + * read in a file + * + * @param string $filename + * @return string + */ + function _read_file($filename) + { + if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) { + $contents = ($size = filesize($filename)) ? fread($fd, $size) : ''; + fclose($fd); + return $contents; + } else { + return false; + } + } + + /** + * get a concrete filename for automagically created content + * + * @param string $auto_base + * @param string $auto_source + * @param string $auto_id + * @return string + * @staticvar string|null + * @staticvar string|null + */ + function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null) + { + $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + $_return = $auto_base . DIRECTORY_SEPARATOR; + + if(isset($auto_id)) { + // make auto_id safe for directory names + $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id))); + // split into separate directories + $_return .= $auto_id . $_compile_dir_sep; + } + + if(isset($auto_source)) { + // make source name safe for filename + $_filename = urlencode(basename($auto_source)); + $_crc32 = sprintf('%08X', crc32($auto_source)); + // prepend %% to avoid name conflicts with + // with $params['auto_id'] names + $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep . + substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32; + $_return .= '%%' . $_crc32 . '%%' . $_filename; + } + + return $_return; + } + + /** + * unlink a file, possibly using expiration time + * + * @param string $resource + * @param integer $exp_time + */ + function _unlink($resource, $exp_time = null) + { + if(isset($exp_time)) { + if(time() - @filemtime($resource) >= $exp_time) { + return @unlink($resource); + } + } else { + return @unlink($resource); + } + } + + /** + * returns an auto_id for auto-file-functions + * + * @param string $cache_id + * @param string $compile_id + * @return string|null + */ + function _get_auto_id($cache_id=null, $compile_id=null) { + if (isset($cache_id)) + return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id; + elseif(isset($compile_id)) + return $compile_id; + else + return null; + } + + /** + * trigger Smarty plugin error + * + * @param string $error_msg + * @param string $tpl_file + * @param integer $tpl_line + * @param string $file + * @param integer $line + * @param integer $error_type + */ + function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null, + $file = null, $line = null, $error_type = E_USER_ERROR) + { + if(isset($file) && isset($line)) { + $info = ' ('.basename($file).", line $line)"; + } else { + $info = ''; + } + if (isset($tpl_line) && isset($tpl_file)) { + $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type); + } else { + $this->trigger_error($error_msg . $info, $error_type); + } + } + + + /** + * callback function for preg_replace, to call a non-cacheable block + * @return string + */ + function _process_compiled_include_callback($match) { + $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3]; + ob_start(); + $_func($this); + $_ret = ob_get_contents(); + ob_end_clean(); + return $_ret; + } + + + /** + * called for included templates + * + * @param string $_smarty_include_tpl_file + * @param string $_smarty_include_vars + */ + + // $_smarty_include_tpl_file, $_smarty_include_vars + + function _smarty_include($params) + { + if ($this->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $params['smarty_include_tpl_file'], + 'depth' => ++$this->_inclusion_depth); + $included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']); + + // config vars are treated as local, so push a copy of the + // current ones onto the front of the stack + array_unshift($this->_config, $this->_config[0]); + + $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']); + + + if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path) + || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + + // pop the local vars off the front of the stack + array_shift($this->_config); + + $this->_inclusion_depth--; + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time; + } + + if ($this->caching) { + $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true; + } + } + + + /** + * get or set an array of cached attributes for function that is + * not cacheable + * @return array + */ + function &_smarty_cache_attrs($cache_serial, $count) { + $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count]; + + if ($this->_cache_including) { + /* return next set of cache_attrs */ + $_return =& current($_cache_attrs); + next($_cache_attrs); + return $_return; + + } else { + /* add a reference to a new set of cache_attrs */ + $_cache_attrs[] = array(); + return $_cache_attrs[count($_cache_attrs)-1]; + + } + + } + + + /** + * wrapper for include() retaining $this + * @return mixed + */ + function _include($filename, $once=false, $params=null) + { + if ($once) { + return include_once($filename); + } else { + return include($filename); + } + } + + + /** + * wrapper for eval() retaining $this + * @return mixed + */ + function _eval($code, $params=null) + { + return eval($code); + } + /**#@-*/ + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/Smarty_Compiler.class.php b/include/smarty/Smarty_Compiler.class.php new file mode 100644 index 000000000..b9cb808c1 --- /dev/null +++ b/include/smarty/Smarty_Compiler.class.php @@ -0,0 +1,2304 @@ + + * @author Andrei Zmievski + * @version 2.6.9 + * @copyright 2001-2005 New Digital Group, Inc. + * @package Smarty + */ + +/* $Id: Smarty_Compiler.class.php,v 1.367 2005/03/30 16:48:41 mohrt Exp $ */ + +/** + * Template compiling class + * @package Smarty + */ +class Smarty_Compiler extends Smarty { + + // internal vars + /**#@+ + * @access private + */ + var $_folded_blocks = array(); // keeps folded template blocks + var $_current_file = null; // the current template being compiled + var $_current_line_no = 1; // line number for error messages + var $_capture_stack = array(); // keeps track of nested capture buffers + var $_plugin_info = array(); // keeps track of plugins to load + var $_init_smarty_vars = false; + var $_permitted_tokens = array('true','false','yes','no','on','off','null'); + var $_db_qstr_regexp = null; // regexps are setup in the constructor + var $_si_qstr_regexp = null; + var $_qstr_regexp = null; + var $_func_regexp = null; + var $_reg_obj_regexp = null; + var $_var_bracket_regexp = null; + var $_num_const_regexp = null; + var $_dvar_guts_regexp = null; + var $_dvar_regexp = null; + var $_cvar_regexp = null; + var $_svar_regexp = null; + var $_avar_regexp = null; + var $_mod_regexp = null; + var $_var_regexp = null; + var $_parenth_param_regexp = null; + var $_func_call_regexp = null; + var $_obj_ext_regexp = null; + var $_obj_start_regexp = null; + var $_obj_params_regexp = null; + var $_obj_call_regexp = null; + var $_cacheable_state = 0; + var $_cache_attrs_count = 0; + var $_nocache_count = 0; + var $_cache_serial = null; + var $_cache_include = null; + + var $_strip_depth = 0; + var $_additional_newline = "\n"; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty_Compiler() + { + // matches double quoted strings: + // "foobar" + // "foo\"bar" + $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; + + // matches single quoted strings: + // 'foobar' + // 'foo\'bar' + $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; + + // matches single or double quoted strings + $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')'; + + // matches bracket portion of vars + // [0] + // [foo] + // [$bar] + $this->_var_bracket_regexp = '\[\$?[\w\.]+\]'; + + // matches numerical constants + // 30 + // -12 + // 13.22 + $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)'; + + // matches $ vars (not objects): + // $foo + // $foo.bar + // $foo.bar.foobar + // $foo[0] + // $foo[$bar] + // $foo[5][blah] + // $foo[5].bar[$foobar][4] + $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))'; + $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]'; + $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp + . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?'; + $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp; + + // matches config vars: + // #foo# + // #foobar123_foo# + $this->_cvar_regexp = '\#\w+\#'; + + // matches section vars: + // %foo.bar% + $this->_svar_regexp = '\%\w+\.\w+\%'; + + // matches all valid variables (no quotes, no modifiers) + $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|' + . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')'; + + // matches valid variable syntax: + // $foo + // $foo + // #foo# + // #foo# + // "text" + // "text" + $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')'; + + // matches valid object call (one level of object nesting allowed in parameters): + // $foo->bar + // $foo->bar() + // $foo->bar("text") + // $foo->bar($foo, $bar, "text") + // $foo->bar($foo, "foo") + // $foo->bar->foo() + // $foo->bar->foo->bar() + // $foo->bar($foo->bar) + // $foo->bar($foo->bar()) + // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar)) + $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')'; + $this->_obj_restricted_param_regexp = '(?:' + . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')' + . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)'; + $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)'; + $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp + . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)'; + $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)'; + $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)'; + + // matches valid modifier syntax: + // |foo + // |@foo + // |foo:"bar" + // |foo:$bar + // |foo:"bar":$foobar + // |foo|bar + // |foo:$foo->bar + $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|' + . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)'; + + // matches valid function name: + // foo123 + // _foo_bar + $this->_func_regexp = '[a-zA-Z_]\w*'; + + // matches valid registered object: + // foo->bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*'; + + // matches valid parameter values: + // true + // $foo + // $foo|bar + // #foo# + // #foo#|bar + // "text" + // "text"|bar + // $foo->bar + $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|' + . $this->_var_regexp . '|' . $this->_num_const_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)'; + + // matches valid parenthesised function parameters: + // + // "text" + // $foo, $bar, "text" + // $foo|bar, "foo"|bar, $foo->bar($foo)|bar + $this->_parenth_param_regexp = '(?:\((?:\w+|' + . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_param_regexp . ')))*)?\))'; + + // matches valid function call: + // foo() + // foo_bar($foo) + // _foo_bar($foo,"bar") + // foo123($foo,$foo->bar(),"foo") + $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:' + . $this->_parenth_param_regexp . '))'; + } + + /** + * compile a resource + * + * sets $compiled_content to the compiled source + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return true + */ + function _compile_file($resource_name, $source_content, &$compiled_content) + { + + if ($this->security) { + // do not allow php syntax to be executed unless specified + if ($this->php_handling == SMARTY_PHP_ALLOW && + !$this->security_settings['PHP_HANDLING']) { + $this->php_handling = SMARTY_PHP_PASSTHRU; + } + } + + $this->_load_filters(); + + $this->_current_file = $resource_name; + $this->_current_line_no = 1; + $ldq = preg_quote($this->left_delimiter, '~'); + $rdq = preg_quote($this->right_delimiter, '~'); + + // run template source through prefilter functions + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) continue; + if ($prefilter[3] || is_callable($prefilter[0])) { + $source_content = call_user_func_array($prefilter[0], + array($source_content, &$this)); + $this->_plugins['prefilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented"); + } + } + } + + /* fetch all special blocks */ + $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s"; + + preg_match_all($search, $source_content, $match, PREG_SET_ORDER); + $this->_folded_blocks = $match; + reset($this->_folded_blocks); + + /* replace special blocks by "{php}" */ + $source_content = preg_replace($search.'e', "'" + . $this->_quote_replace($this->left_delimiter) . 'php' + . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'" + . $this->_quote_replace($this->right_delimiter) + . "'" + , $source_content); + + /* Gather all template tags. */ + preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match); + $template_tags = $_match[1]; + /* Split content by template tags to obtain non-template content. */ + $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content); + + /* loop through text blocks */ + for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) { + /* match anything resembling php tags */ + if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) { + /* replace tags with placeholders to prevent recursive replacements */ + $sp_match[1] = array_unique($sp_match[1]); + usort($sp_match[1], '_smarty_sort_length'); + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]); + } + /* process each one */ + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + if ($this->php_handling == SMARTY_PHP_PASSTHRU) { + /* echo php contents */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', ''."\n", $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_QUOTE) { + /* quote php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_REMOVE) { + /* remove php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]); + } else { + /* SMARTY_PHP_ALLOW, but echo non php starting tags */ + $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', ''."\n", $sp_match[1][$curr_sp]); + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]); + } + } + } + } + + /* Compile the template tags into PHP code. */ + $compiled_tags = array(); + for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) { + $this->_current_line_no += substr_count($text_blocks[$i], "\n"); + $compiled_tags[] = $this->_compile_tag($template_tags[$i]); + $this->_current_line_no += substr_count($template_tags[$i], "\n"); + } + if (count($this->_tag_stack)>0) { + list($_open_tag, $_line_no) = end($this->_tag_stack); + $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__); + return; + } + + /* Reformat $text_blocks between 'strip' and '/strip' tags, + removing spaces, tabs and newlines. */ + $strip = false; + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '{strip}') { + $compiled_tags[$i] = ''; + $strip = true; + /* remove leading whitespaces */ + $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]); + } + if ($strip) { + /* strip all $text_blocks before the next '/strip' */ + for ($j = $i + 1; $j < $for_max; $j++) { + /* remove leading and trailing whitespaces of each line */ + $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]); + if ($compiled_tags[$j] == '{/strip}') { + /* remove trailing whitespaces from the last text_block */ + $text_blocks[$j] = rtrim($text_blocks[$j]); + } + $text_blocks[$j] = ""\'", "\\"=>"\\\\")) . "'; ?>"; + if ($compiled_tags[$j] == '{/strip}') { + $compiled_tags[$j] = "\n"; /* slurped by php, but necessary + if a newline is following the closing strip-tag */ + $strip = false; + $i = $j; + break; + } + } + } + } + $compiled_content = ''; + + /* Interleave the compiled contents and text blocks to get the final result. */ + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '') { + // tag result empty, remove first newline from following text block + $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]); + } + $compiled_content .= $text_blocks[$i].$compiled_tags[$i]; + } + $compiled_content .= $text_blocks[$i]; + + // remove \n from the end of the file, if any + if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) { + $compiled_content = substr($compiled_content, 0, -1); + } + + if (!empty($this->_cache_serial)) { + $compiled_content = "_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content; + } + + // remove unnecessary close/open tags + $compiled_content = preg_replace('~\?>\n?<\?php~', '', $compiled_content); + + // run compiled template through postfilter functions + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) continue; + if ($postfilter[3] || is_callable($postfilter[0])) { + $compiled_content = call_user_func_array($postfilter[0], + array($compiled_content, &$this)); + $this->_plugins['postfilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented"); + } + } + } + + // put header at the top of the compiled template + $template_header = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n"; + + /* Emit code to load needed plugins. */ + $this->_plugins_code = ''; + if (count($this->_plugin_info)) { + $_plugins_params = "array('plugins' => array("; + foreach ($this->_plugin_info as $plugin_type => $plugins) { + foreach ($plugins as $plugin_name => $plugin_info) { + $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], "; + $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),'; + } + } + $_plugins_params .= '))'; + $plugins_code = "\n"; + $template_header .= $plugins_code; + $this->_plugin_info = array(); + $this->_plugins_code = $plugins_code; + } + + if ($this->_init_smarty_vars) { + $template_header .= "\n"; + $this->_init_smarty_vars = false; + } + + $compiled_content = $template_header . $compiled_content; + return true; + } + + /** + * Compile a template tag + * + * @param string $template_tag + * @return string + */ + function _compile_tag($template_tag) + { + /* Matched comment. */ + if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*') + return ''; + + /* Split tag into two three parts: command, command modifiers and the arguments. */ + if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + (?:\s+(.*))?$ + ~xs', $template_tag, $match)) { + $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $tag_command = $match[1]; + $tag_modifier = isset($match[2]) ? $match[2] : null; + $tag_args = isset($match[3]) ? $match[3] : null; + + if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) { + /* tag name is a variable or object */ + $_return = $this->_parse_var_props($tag_command . $tag_modifier); + return "" . $this->_additional_newline; + } + + /* If the tag name is a registered object, we process it. */ + if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) { + return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier); + } + + switch ($tag_command) { + case 'include': + return $this->_compile_include_tag($tag_args); + + case 'include_php': + return $this->_compile_include_php_tag($tag_args); + + case 'if': + $this->_push_tag('if'); + return $this->_compile_if_tag($tag_args); + + case 'else': + list($_open_tag) = end($this->_tag_stack); + if ($_open_tag != 'if' && $_open_tag != 'elseif') + $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__); + else + $this->_push_tag('else'); + return ''; + + case 'elseif': + list($_open_tag) = end($this->_tag_stack); + if ($_open_tag != 'if' && $_open_tag != 'elseif') + $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__); + if ($_open_tag == 'if') + $this->_push_tag('elseif'); + return $this->_compile_if_tag($tag_args, true); + + case '/if': + $this->_pop_tag('if'); + return ''; + + case 'capture': + return $this->_compile_capture_tag(true, $tag_args); + + case '/capture': + return $this->_compile_capture_tag(false); + + case 'ldelim': + return $this->left_delimiter; + + case 'rdelim': + return $this->right_delimiter; + + case 'section': + $this->_push_tag('section'); + return $this->_compile_section_start($tag_args); + + case 'sectionelse': + $this->_push_tag('sectionelse'); + return ""; + break; + + case '/section': + $_open_tag = $this->_pop_tag('section'); + if ($_open_tag == 'sectionelse') + return ""; + else + return ""; + + case 'foreach': + $this->_push_tag('foreach'); + return $this->_compile_foreach_start($tag_args); + break; + + case 'foreachelse': + $this->_push_tag('foreachelse'); + return ""; + + case '/foreach': + $_open_tag = $this->_pop_tag('foreach'); + if ($_open_tag == 'foreachelse') + return ""; + else + return ""; + break; + + case 'strip': + case '/strip': + if ($tag_command{0}=='/') { + $this->_pop_tag('strip'); + if (--$this->_strip_depth==0) { /* outermost closing {/strip} */ + $this->_additional_newline = "\n"; + return '{' . $tag_command . '}'; + } + } else { + $this->_push_tag('strip'); + if ($this->_strip_depth++==0) { /* outermost opening {strip} */ + $this->_additional_newline = ""; + return '{' . $tag_command . '}'; + } + } + return ''; + + case 'php': + /* handle folded tags replaced by {php} */ + list(, $block) = each($this->_folded_blocks); + $this->_current_line_no += substr_count($block[0], "\n"); + /* the number of matched elements in the regexp in _compile_file() + determins the type of folded tag that was found */ + switch (count($block)) { + case 2: /* comment */ + return ''; + + case 3: /* literal */ + return ""\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline; + + case 4: /* php */ + if ($this->security && !$this->security_settings['PHP_TAGS']) { + $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__); + return; + } + return ''; + } + break; + + case 'insert': + return $this->_compile_insert_tag($tag_args); + + default: + if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) { + return $output; + } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) { + return $output; + } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) { + return $output; + } else { + $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__); + } + + } + } + + + /** + * compile the custom compiler tag + * + * sets $output to the compiled custom compiler tag + * @param string $tag_command + * @param string $tag_args + * @param string $output + * @return boolean + */ + function _compile_compiler_tag($tag_command, $tag_args, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the compiler function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['compiler'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['compiler'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "compiler function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_compiler_' . $tag_command; + if (!is_callable($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true); + } + } + + /* + * True return value means that we either found a plugin or a + * dynamically registered function. False means that we didn't and the + * compiler should now emit code to load custom function plugin for this + * tag. + */ + if ($found) { + if ($have_function) { + $output = call_user_func_array($plugin_func, array($tag_args, &$this)); + if($output != '') { + $output = '_push_cacheable_state('compiler', $tag_command) + . $output + . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>'; + } + } else { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + } + return true; + } else { + return false; + } + } + + + /** + * compile block function tag + * + * sets $output to compiled block function tag + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @param string $output + * @return boolean + */ + function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + if ($tag_command{0} == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else + $start_tag = true; + + $found = false; + $have_function = true; + + /* + * First we check if the block function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['block'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['block'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "block function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_block_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* + * Even though we've located the plugin function, compilation + * happens only once, so the plugin will still need to be loaded + * at runtime for future requests. + */ + $this->_add_plugin('block', $tag_command); + + if ($start_tag) + $this->_push_tag($tag_command); + else + $this->_pop_tag($tag_command); + + if ($start_tag) { + $output = '_push_cacheable_state('block', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs=''); + $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); '; + $output .= $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat=true);'; + $output .= 'while ($_block_repeat) { ob_start(); ?>'; + } else { + $output = '_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat=false)'; + if ($tag_modifier != '') { + $this->_parse_modifiers($_out_tag_text, $tag_modifier); + } + $output .= 'echo '.$_out_tag_text.'; } '; + $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>'; + } + + return true; + } + + + /** + * compile custom function tag + * + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @return string + */ + function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the custom function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['function'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['function'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "custom function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_function_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* declare plugin to be loaded on display of the template that + we compile right now */ + $this->_add_plugin('function', $tag_command); + + $_cacheable_state = $this->_push_cacheable_state('function', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs=''); + + $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)"; + if($tag_modifier != '') { + $this->_parse_modifiers($output, $tag_modifier); + } + + if($output != '') { + $output = '_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline; + } + + return true; + } + + /** + * compile a registered object tag + * + * @param string $tag_command + * @param array $attrs + * @param string $tag_modifier + * @return string + */ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + if ($tag_command{0} == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else { + $start_tag = true; + } + + list($object, $obj_comp) = explode('->', $tag_command); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + unset($attrs['assign']); + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if($this->_reg_objects[$object][2]) { + // smarty object argument format + $args = "array(".implode(',', (array)$arg_list)."), \$this"; + } else { + // traditional argument format + $args = implode(',', array_values($attrs)); + if (empty($args)) { + $args = 'null'; + } + } + + $prefix = ''; + $postfix = ''; + $newline = ''; + if(!is_object($this->_reg_objects[$object][0])) { + $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) { + $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) { + // method + if(in_array($obj_comp, $this->_reg_objects[$object][3])) { + // block method + if ($start_tag) { + $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); "; + $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); "; + $prefix .= "while (\$_block_repeat) { ob_start();"; + $return = null; + $postfix = ''; + } else { + $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); "; + $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat=false)"; + $postfix = "} array_pop(\$this->_tag_stack);"; + } + } else { + // non-block method + $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)"; + } + } else { + // property + $return = "\$this->_reg_objects['$object'][0]->$obj_comp"; + } + + if($return != null) { + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if(!empty($_assign_var)) { + $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);"; + } else { + $output = 'echo ' . $return . ';'; + $newline = $this->_additional_newline; + } + } else { + $output = ''; + } + + return '" . $newline; + } + + /** + * Compile {insert ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_insert_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $name = $this->_dequote($attrs['name']); + + if (empty($name)) { + $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!empty($attrs['script'])) { + $delayed_loading = true; + } else { + $delayed_loading = false; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $this->_add_plugin('insert', $name, $delayed_loading); + + $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))"; + + return "" . $this->_additional_newline; + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__); + } + + foreach ($attrs as $arg_name => $arg_value) { + if ($arg_name == 'file') { + $include_file = $arg_value; + continue; + } else if ($arg_name == 'assign') { + $assign_var = $arg_value; + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $output = '_tpl_vars;\n"; + + + $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))"; + $output .= "\$this->_smarty_include($_params);\n" . + "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" . + "unset(\$_smarty_tpl_vars);\n"; + + if (isset($assign_var)) { + $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n"; + } + + $output .= ' ?>'; + + return $output; + + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_php_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']); + $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true'; + + $arg_list = array(); + foreach($attrs as $arg_name => $arg_value) { + if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') { + if(is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))"; + + return "" . $this->_additional_newline; + } + + + /** + * Compile {section ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_section_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + $output = '_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__); + } + + $output .= "unset(\$this->_sections[$section_name]);\n"; + $section_props = "\$this->_sections[$section_name]"; + + foreach ($attrs as $attr_name => $attr_value) { + switch ($attr_name) { + case 'loop': + $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n"; + break; + + case 'show': + if (is_bool($attr_value)) + $show_attr_value = $attr_value ? 'true' : 'false'; + else + $show_attr_value = "(bool)$attr_value"; + $output .= "{$section_props}['show'] = $show_attr_value;\n"; + break; + + case 'name': + $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + break; + + case 'max': + case 'start': + $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; + break; + + case 'step': + $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n"; + break; + + default: + $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + } + + if (!isset($attrs['show'])) + $output .= "{$section_props}['show'] = true;\n"; + + if (!isset($attrs['loop'])) + $output .= "{$section_props}['loop'] = 1;\n"; + + if (!isset($attrs['max'])) + $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; + else + $output .= "if ({$section_props}['max'] < 0)\n" . + " {$section_props}['max'] = {$section_props}['loop'];\n"; + + if (!isset($attrs['step'])) + $output .= "{$section_props}['step'] = 1;\n"; + + if (!isset($attrs['start'])) + $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n"; + else { + $output .= "if ({$section_props}['start'] < 0)\n" . + " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" . + "else\n" . + " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n"; + } + + $output .= "if ({$section_props}['show']) {\n"; + if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) { + $output .= " {$section_props}['total'] = {$section_props}['loop'];\n"; + } else { + $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n"; + } + $output .= " if ({$section_props}['total'] == 0)\n" . + " {$section_props}['show'] = false;\n" . + "} else\n" . + " {$section_props}['total'] = 0;\n"; + + $output .= "if ({$section_props}['show']):\n"; + $output .= " + for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; + {$section_props}['iteration'] <= {$section_props}['total']; + {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n"; + $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n"; + $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n"; + $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n"; + $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n"; + $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n"; + + $output .= "?>"; + + return $output; + } + + + /** + * Compile {foreach ...} tag. + * + * @param string $tag_args + * @return string + */ + function _compile_foreach_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['from'])) { + return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + $from = $attrs['from']; + + if (empty($attrs['item'])) { + return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + $item = $this->_dequote($attrs['item']); + if (!preg_match('~^\w+$~', $item)) { + return $this->_syntax_error("'foreach: item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__); + } + + if (isset($attrs['key'])) { + $key = $this->_dequote($attrs['key']); + if (!preg_match('~^\w+$~', $key)) { + return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__); + } + $key_part = "\$this->_tpl_vars['$key'] => "; + } else { + $key = null; + $key_part = ''; + } + + if (isset($attrs['name'])) { + $name = $attrs['name']; + } else { + $name = null; + } + + $output = '_foreach[$name]"; + $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n"; + $output .= "if ({$foreach_props}['total'] > 0):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + $output .= " {$foreach_props}['iteration']++;\n"; + } else { + $output .= "if (count(\$_from)):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + } + $output .= '?>'; + + return $output; + } + + + /** + * Compile {capture} .. {/capture} tags + * + * @param boolean $start true if this is the {capture} tag + * @param string $tag_args + * @return string + */ + + function _compile_capture_tag($start, $tag_args = '') + { + $attrs = $this->_parse_attrs($tag_args); + + if ($start) { + if (isset($attrs['name'])) + $buffer = $attrs['name']; + else + $buffer = "'default'"; + + if (isset($attrs['assign'])) + $assign = $attrs['assign']; + else + $assign = null; + $output = ""; + $this->_capture_stack[] = array($buffer, $assign); + } else { + list($buffer, $assign) = array_pop($this->_capture_stack); + $output = "_smarty_vars['capture'][$buffer] = ob_get_contents(); "; + if (isset($assign)) { + $output .= " \$this->assign($assign, ob_get_contents());"; + } + $output .= "ob_end_clean(); ?>"; + } + + return $output; + } + + /** + * Compile {if ...} tag + * + * @param string $tag_args + * @param boolean $elseif if true, uses elseif instead of if + * @return string + */ + function _compile_if_tag($tag_args, $elseif = false) + { + + /* Tokenize args for 'if' tag. */ + preg_match_all('~(?> + ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call + ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)? | # var or quoted string + \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@ | # valid non-word token + \b\w+\b | # valid word token + \S+ # anything else + )~x', $tag_args, $match); + + $tokens = $match[0]; + + // make sure we have balanced parenthesis + $token_count = array_count_values($tokens); + if(isset($token_count['(']) && $token_count['('] != $token_count[')']) { + $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + + $is_arg_stack = array(); + + for ($i = 0; $i < count($tokens); $i++) { + + $token = &$tokens[$i]; + + switch (strtolower($token)) { + case '!': + case '%': + case '!==': + case '==': + case '===': + case '>': + case '<': + case '!=': + case '<>': + case '<<': + case '>>': + case '<=': + case '>=': + case '&&': + case '||': + case '|': + case '^': + case '&': + case '~': + case ')': + case ',': + case '+': + case '-': + case '*': + case '/': + case '@': + break; + + case 'eq': + $token = '=='; + break; + + case 'ne': + case 'neq': + $token = '!='; + break; + + case 'lt': + $token = '<'; + break; + + case 'le': + case 'lte': + $token = '<='; + break; + + case 'gt': + $token = '>'; + break; + + case 'ge': + case 'gte': + $token = '>='; + break; + + case 'and': + $token = '&&'; + break; + + case 'or': + $token = '||'; + break; + + case 'not': + $token = '!'; + break; + + case 'mod': + $token = '%'; + break; + + case '(': + array_push($is_arg_stack, $i); + break; + + case 'is': + /* If last token was a ')', we operate on the parenthesized + expression. The start of the expression is on the stack. + Otherwise, we operate on the last encountered token. */ + if ($tokens[$i-1] == ')') + $is_arg_start = array_pop($is_arg_stack); + else + $is_arg_start = $i-1; + /* Construct the argument for 'is' expression, so it knows + what to operate on. */ + $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); + + /* Pass all tokens from next one until the end to the + 'is' expression parsing function. The function will + return modified tokens, where the first one is the result + of the 'is' expression and the rest are the tokens it + didn't touch. */ + $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); + + /* Replace the old tokens with the new ones. */ + array_splice($tokens, $is_arg_start, count($tokens), $new_tokens); + + /* Adjust argument start so that it won't change from the + current position for the next iteration. */ + $i = $is_arg_start; + break; + + default: + if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) { + // function call + if($this->security && + !in_array($token, $this->security_settings['IF_FUNCS'])) { + $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') { + // variable function call + $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) { + // object or variable + $token = $this->_parse_var_props($token); + } elseif(is_numeric($token)) { + // number, skip it + } else { + $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + } + } + + if ($elseif) + return ''; + else + return ''; + } + + + function _compile_arg_list($type, $name, $attrs, &$cache_code) { + $arg_list = array(); + + if (isset($type) && isset($name) + && isset($this->_plugins[$type]) + && isset($this->_plugins[$type][$name]) + && empty($this->_plugins[$type][$name][4]) + && is_array($this->_plugins[$type][$name][5]) + ) { + /* we have a list of parameters that should be cached */ + $_cache_attrs = $this->_plugins[$type][$name][5]; + $_count = $this->_cache_attrs_count++; + $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');"; + + } else { + /* no parameters are cached */ + $_cache_attrs = null; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + if (is_null($arg_value)) + $arg_value = 'null'; + if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) { + $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)"; + } else { + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + return $arg_list; + } + + /** + * Parse is expression + * + * @param string $is_arg + * @param array $tokens + * @return array + */ + function _parse_is_expr($is_arg, $tokens) + { + $expr_end = 0; + $negate_expr = false; + + if (($first_token = array_shift($tokens)) == 'not') { + $negate_expr = true; + $expr_type = array_shift($tokens); + } else + $expr_type = $first_token; + + switch ($expr_type) { + case 'even': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))"; + } else + $expr = "!(1 & $is_arg)"; + break; + + case 'odd': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))"; + } else + $expr = "(1 & $is_arg)"; + break; + + case 'div': + if (@$tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")"; + } else { + $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + + default: + $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if ($negate_expr) { + $expr = "!($expr)"; + } + + array_splice($tokens, 0, $expr_end, $expr); + + return $tokens; + } + + + /** + * Parse attribute string + * + * @param string $tag_args + * @return array + */ + function _parse_attrs($tag_args) + { + + /* Tokenize tag attributes. */ + preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+) + )+ | + [=] + ~x', $tag_args, $match); + $tokens = $match[0]; + + $attrs = array(); + /* Parse state: + 0 - expecting attribute name + 1 - expecting '=' + 2 - expecting attribute value (not '=') */ + $state = 0; + + foreach ($tokens as $token) { + switch ($state) { + case 0: + /* If the token is a valid identifier, we set attribute name + and go to state 1. */ + if (preg_match('~^\w+$~', $token)) { + $attr_name = $token; + $state = 1; + } else + $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 1: + /* If the token is '=', then we go to state 2. */ + if ($token == '=') { + $state = 2; + } else + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 2: + /* If token is not '=', we set the attribute value and go to + state 0. */ + if ($token != '=') { + /* We booleanize the token if it's a non-quoted possible + boolean value. */ + if (preg_match('~^(on|yes|true)$~', $token)) { + $token = 'true'; + } else if (preg_match('~^(off|no|false)$~', $token)) { + $token = 'false'; + } else if ($token == 'null') { + $token = 'null'; + } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) { + /* treat integer literally */ + } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) { + /* treat as a string, double-quote it escaping quotes */ + $token = '"'.addslashes($token).'"'; + } + + $attrs[$attr_name] = $token; + $state = 0; + } else + $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__); + break; + } + $last_token = $token; + } + + if($state != 0) { + if($state == 1) { + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + } else { + $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } + + $this->_parse_vars_props($attrs); + + return $attrs; + } + + /** + * compile multiple variables and section properties tokens into + * PHP code + * + * @param array $tokens + */ + function _parse_vars_props(&$tokens) + { + foreach($tokens as $key => $val) { + $tokens[$key] = $this->_parse_var_props($val); + } + } + + /** + * compile single variable and section properties token into + * PHP code + * + * @param string $val + * @param string $tag_attrs + * @return string + */ + function _parse_var_props($val) + { + $val = trim($val); + + if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) { + // $ variable or object + $return = $this->_parse_var($match[1]); + $modifiers = $match[2]; + if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) { + $_default_mod_string = implode('|',(array)$this->default_modifiers); + $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers; + } + $this->_parse_modifiers($return, $modifiers); + return $return; + } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // double quoted text + preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + $return = $this->_expand_quoted_text($match[1]); + if($match[2] != '') { + $this->_parse_modifiers($return, $match[2]); + } + return $return; + } + elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // numerical constant + preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + if($match[2] != '') { + $this->_parse_modifiers($match[1], $match[2]); + return $match[1]; + } + } + elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // single quoted text + preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + if($match[2] != '') { + $this->_parse_modifiers($match[1], $match[2]); + return $match[1]; + } + } + elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // config var + return $this->_parse_conf_var($val); + } + elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // section var + return $this->_parse_section_prop($val); + } + elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) { + // literal string + return $this->_expand_quoted_text('"' . $val .'"'); + } + return $val; + } + + /** + * expand quoted text with embedded variables + * + * @param string $var_expr + * @return string + */ + function _expand_quoted_text($var_expr) + { + // if contains unescaped $, expand it + if(preg_match_all('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."', $var_expr); + } + $_return = preg_replace('~\.""|(?_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE); + + if(count($_math_vars) > 1) { + $_first_var = ""; + $_complete_var = ""; + $_output = ""; + // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter) + foreach($_math_vars as $_k => $_math_var) { + $_math_var = $_math_vars[$_k]; + + if(!empty($_math_var) || is_numeric($_math_var)) { + // hit a math operator, so process the stuff which came before it + if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) { + $_has_math = true; + if(!empty($_complete_var) || is_numeric($_complete_var)) { + $_output .= $this->_parse_var($_complete_var); + } + + // just output the math operator to php + $_output .= $_math_var; + + if(empty($_first_var)) + $_first_var = $_complete_var; + + $_complete_var = ""; + } else { + $_complete_var .= $_math_var; + } + } + } + if($_has_math) { + if(!empty($_complete_var) || is_numeric($_complete_var)) + $_output .= $this->_parse_var($_complete_var); + + // get the modifiers working (only the last var from math + modifier is left) + $var_expr = $_complete_var; + } + } + + // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit) + if(is_numeric($var_expr{0})) + $_var_ref = $var_expr; + else + $_var_ref = substr($var_expr, 1); + + if(!$_has_math) { + + // get [foo] and .foo and ->foo and (...) pieces + preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match); + + $_indexes = $match[0]; + $_var_name = array_shift($_indexes); + + /* Handle $smarty.* variable references as a special case. */ + if ($_var_name == 'smarty') { + /* + * If the reference could be compiled, use the compiled output; + * otherwise, fall back on the $smarty variable generated at + * run-time. + */ + if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) { + $_output = $smarty_ref; + } else { + $_var_name = substr(array_shift($_indexes), 1); + $_output = "\$this->_smarty_vars['$_var_name']"; + } + } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) { + // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers + if(count($_indexes) > 0) + { + $_var_name .= implode("", $_indexes); + $_indexes = array(); + } + $_output = $_var_name; + } else { + $_output = "\$this->_tpl_vars['$_var_name']"; + } + + foreach ($_indexes as $_index) { + if ($_index{0} == '[') { + $_index = substr($_index, 1, -1); + if (is_numeric($_index)) { + $_output .= "[$_index]"; + } elseif ($_index{0} == '$') { + if (strpos($_index, '.') !== false) { + $_output .= '[' . $this->_parse_var($_index) . ']'; + } else { + $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]"; + } + } else { + $_var_parts = explode('.', $_index); + $_var_section = $_var_parts[0]; + $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index'; + $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]"; + } + } else if ($_index{0} == '.') { + if ($_index{1} == '$') + $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]"; + else + $_output .= "['" . substr($_index, 1) . "']"; + } else if (substr($_index,0,2) == '->') { + if(substr($_index,2,2) == '__') { + $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif($this->security && substr($_index, 2, 1) == '_') { + $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif ($_index{2} == '$') { + if ($this->security) { + $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } else { + $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}'; + } + } else { + $_output .= $_index; + } + } elseif ($_index{0} == '(') { + $_index = $this->_parse_parenth_args($_index); + $_output .= $_index; + } else { + $_output .= $_index; + } + } + } + + return $_output; + } + + /** + * parse arguments in function call parenthesis + * + * @param string $parenth_args + * @return string + */ + function _parse_parenth_args($parenth_args) + { + preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match); + $orig_vals = $match = $match[0]; + $this->_parse_vars_props($match); + $replace = array(); + for ($i = 0, $count = count($match); $i < $count; $i++) { + $replace[$orig_vals[$i]] = $match[$i]; + } + return strtr($parenth_args, $replace); + } + + /** + * parse configuration variable expression into PHP code + * + * @param string $conf_var_expr + */ + function _parse_conf_var($conf_var_expr) + { + $parts = explode('|', $conf_var_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + $var_name = substr($var_ref, 1, -1); + + $output = "\$this->_config[0]['vars']['$var_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + /** + * parse section property expression into PHP code + * + * @param string $section_prop_expr + * @return string + */ + function _parse_section_prop($section_prop_expr) + { + $parts = explode('|', $section_prop_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match); + $section_name = $match[1]; + $prop_name = $match[2]; + + $output = "\$this->_sections['$section_name']['$prop_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + + /** + * parse modifier chain into PHP code + * + * sets $output to parsed modified chain + * @param string $output + * @param string $modifier_string + */ + function _parse_modifiers(&$output, $modifier_string) + { + preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match); + list(, $_modifiers, $modifier_arg_strings) = $_match; + + for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) { + $_modifier_name = $_modifiers[$_i]; + + if($_modifier_name == 'smarty') { + // skip smarty modifier + continue; + } + + preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match); + $_modifier_args = $_match[1]; + + if ($_modifier_name{0} == '@') { + $_map_array = false; + $_modifier_name = substr($_modifier_name, 1); + } else { + $_map_array = true; + } + + if (empty($this->_plugins['modifier'][$_modifier_name]) + && !$this->_get_plugin_filepath('modifier', $_modifier_name) + && function_exists($_modifier_name)) { + if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) { + $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } else { + $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false); + } + } + $this->_add_plugin('modifier', $_modifier_name); + + $this->_parse_vars_props($_modifier_args); + + if($_modifier_name == 'default') { + // supress notifications of default modifier vars and args + if($output{0} == '$') { + $output = '@' . $output; + } + if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') { + $_modifier_args[0] = '@' . $_modifier_args[0]; + } + } + if (count($_modifier_args) > 0) + $_modifier_args = ', '.implode(', ', $_modifier_args); + else + $_modifier_args = ''; + + if ($_map_array) { + $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))"; + + } else { + + $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)"; + + } + } + } + + + /** + * add plugin + * + * @param string $type + * @param string $name + * @param boolean? $delayed_loading + */ + function _add_plugin($type, $name, $delayed_loading = null) + { + if (!isset($this->_plugin_info[$type])) { + $this->_plugin_info[$type] = array(); + } + if (!isset($this->_plugin_info[$type][$name])) { + $this->_plugin_info[$type][$name] = array($this->_current_file, + $this->_current_line_no, + $delayed_loading); + } + } + + + /** + * Compiles references of type $smarty.foo + * + * @param string $indexes + * @return string + */ + function _compile_smarty_ref(&$indexes) + { + /* Extract the reference name. */ + $_ref = substr($indexes[0], 1); + foreach($indexes as $_index_no=>$_index) { + if ($_index{0} != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) { + $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + } + + switch ($_ref) { + case 'now': + $compiled_ref = 'time()'; + $_max_index = 1; + break; + + case 'foreach': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $_propname = substr($indexes[1], 1); + $_max_index = 1; + switch ($_propname) { + case 'index': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)"; + break; + + case 'first': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)"; + break; + + case 'last': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])"; + break; + + case 'show': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)"; + break; + + default: + unset($_max_index); + $compiled_ref = "\$this->_foreach[$_var]"; + } + break; + + case 'section': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = "\$this->_sections[$_var]"; + break; + + case 'get': + $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']"; + break; + + case 'post': + $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']"; + break; + + case 'cookies': + $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']"; + break; + + case 'env': + $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']"; + break; + + case 'server': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']"; + break; + + case 'session': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']"; + break; + + /* + * These cases are handled either at run-time or elsewhere in the + * compiler. + */ + case 'request': + if ($this->request_use_auto_globals) { + $compiled_ref = '$_REQUEST'; + break; + } else { + $this->_init_smarty_vars = true; + } + return null; + + case 'capture': + return null; + + case 'template': + $compiled_ref = "'$this->_current_file'"; + $_max_index = 1; + break; + + case 'version': + $compiled_ref = "'$this->_version'"; + $_max_index = 1; + break; + + case 'const': + if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) { + $this->_syntax_error("(secure mode) constants not permitted", + E_USER_WARNING, __FILE__, __LINE__); + return; + } + array_shift($indexes); + if (preg_match('!^\.\w+$!', $indexes[0])) { + $compiled_ref = '@' . substr($indexes[0], 1); + } else { + $_val = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = '@constant(' . $_val . ')'; + } + $_max_index = 1; + break; + + case 'config': + $compiled_ref = "\$this->_config[0]['vars']"; + $_max_index = 3; + break; + + case 'ldelim': + $compiled_ref = "'$this->left_delimiter'"; + break; + + case 'rdelim': + $compiled_ref = "'$this->right_delimiter'"; + break; + + default: + $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if (isset($_max_index) && count($indexes) > $_max_index) { + $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + + array_shift($indexes); + return $compiled_ref; + } + + /** + * compiles call to plugin of type $type with name $name + * returns a string containing the function-name or method call + * without the paramter-list that would have follow to make the + * call valid php-syntax + * + * @param string $type + * @param string $name + * @return string + */ + function _compile_plugin_call($type, $name) { + if (isset($this->_plugins[$type][$name])) { + /* plugin loaded */ + if (is_array($this->_plugins[$type][$name][0])) { + return ((is_object($this->_plugins[$type][$name][0][0])) ? + "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */ + : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */ + ). $this->_plugins[$type][$name][0][1]; + + } else { + /* function callback */ + return $this->_plugins[$type][$name][0]; + + } + } else { + /* plugin not loaded -> auto-loadable-plugin */ + return 'smarty_'.$type.'_'.$name; + + } + } + + /** + * load pre- and post-filters + */ + function _load_filters() + { + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) { + unset($this->_plugins['prefilter'][$filter_name]); + $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) { + unset($this->_plugins['postfilter'][$filter_name]); + $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + } + + + /** + * Quote subpattern references + * + * @param string $string + * @return string + */ + function _quote_replace($string) + { + return strtr($string, array('\\' => '\\\\', '$' => '\\$')); + } + + /** + * display Smarty syntax error + * + * @param string $error_msg + * @param integer $error_type + * @param string $file + * @param integer $line + */ + function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null) + { + $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type); + } + + + /** + * check if the compilation changes from cacheable to + * non-cacheable state with the beginning of the current + * plugin. return php-code to reflect the transition. + * @return string + */ + function _push_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || 0<$this->_cacheable_state++) return ''; + if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty')); + $_ret = 'if ($this->caching && !$this->_cache_including) { echo \'{nocache:' + . $this->_cache_serial . '#' . $this->_nocache_count + . '}\';}'; + return $_ret; + } + + + /** + * check if the compilation changes from non-cacheable to + * cacheable state with the end of the current plugin return + * php-code to reflect the transition. + * @return string + */ + function _pop_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || --$this->_cacheable_state>0) return ''; + return 'if ($this->caching && !$this->_cache_including) { echo \'{/nocache:' + . $this->_cache_serial . '#' . ($this->_nocache_count++) + . '}\';}'; + } + + + /** + * push opening tag-name, file-name and line-number on the tag-stack + * @param string the opening tag's name + */ + function _push_tag($open_tag) + { + array_push($this->_tag_stack, array($open_tag, $this->_current_line_no)); + } + + /** + * pop closing tag-name + * raise an error if this stack-top doesn't match with the closing tag + * @param string the closing tag's name + * @return string the opening tag's name + */ + function _pop_tag($close_tag) + { + $message = ''; + if (count($this->_tag_stack)>0) { + list($_open_tag, $_line_no) = array_pop($this->_tag_stack); + if ($close_tag == $_open_tag) { + return $_open_tag; + } + if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) { + return $this->_pop_tag($close_tag); + } + if ($close_tag == 'section' && $_open_tag == 'sectionelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($_open_tag == 'else' || $_open_tag == 'elseif') { + $_open_tag = 'if'; + } elseif ($_open_tag == 'sectionelse') { + $_open_tag = 'section'; + } elseif ($_open_tag == 'foreachelse') { + $_open_tag = 'foreach'; + } + $message = " expected {/$_open_tag} (opened line $_line_no)."; + } + $this->_syntax_error("mismatched tag {/$close_tag}.$message", + E_USER_ERROR, __FILE__, __LINE__); + } + +} + +/** + * compare to values by their string length + * + * @access private + * @param string $a + * @param string $b + * @return 0|-1|1 + */ +function _smarty_sort_length($a, $b) +{ + if($a == $b) + return 0; + + if(strlen($a) == strlen($b)) + return ($a > $b) ? -1 : 1; + + return (strlen($a) > strlen($b)) ? -1 : 1; +} + + +/* vim: set et: */ + +?> diff --git a/include/smarty/debug.tpl b/include/smarty/debug.tpl new file mode 100644 index 000000000..7f1c9d425 --- /dev/null +++ b/include/smarty/debug.tpl @@ -0,0 +1,64 @@ +{* Smarty *} + +{* debug.tpl, last updated version 2.0.1 *} + +{assign_debug_info} + +{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} +
+ + + {section name=templates loop=$_debug_tpls} + + {sectionelse} + + {/section} + + {section name=vars loop=$_debug_keys} + + {sectionelse} + + {/section} + + {section name=config_vars loop=$_debug_config_keys} + + {sectionelse} + + {/section} +
Smarty Debug Console
included templates & config files (load time in seconds):
{section name=indent loop=$_debug_tpls[templates].depth}   {/section}{$_debug_tpls[templates].filename|escape:html}{if isset($_debug_tpls[templates].exec_time)} ({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}{/if}
no templates included
assigned template variables:
{ldelim}${$_debug_keys[vars]}{rdelim}{$_debug_vals[vars]|@debug_print_var}
no template variables assigned
assigned config file variables (outer template scope):
{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}{$_debug_config_vals[config_vars]|@debug_print_var}
no config vars assigned
+ +{else} + +{/if} diff --git a/include/smarty/internals/core.assemble_plugin_filepath.php b/include/smarty/internals/core.assemble_plugin_filepath.php new file mode 100644 index 000000000..690d3ddbc --- /dev/null +++ b/include/smarty/internals/core.assemble_plugin_filepath.php @@ -0,0 +1,67 @@ +plugins_dir as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + // see if path is relative + if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) { + $_relative_paths[] = $_plugin_dir; + // relative path, see if it is in the SMARTY_DIR + if (@is_readable(SMARTY_DIR . $_plugin_filepath)) { + $_return = SMARTY_DIR . $_plugin_filepath; + break; + } + } + // try relative to cwd (or absolute) + if (@is_readable($_plugin_filepath)) { + $_return = $_plugin_filepath; + break; + } + } + + if($_return === false) { + // still not found, try PHP include_path + if(isset($_relative_paths)) { + foreach ((array)$_relative_paths as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + $_params = array('file_path' => $_plugin_filepath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_return = $_params['new_file_path']; + break; + } + } + } + } + $_filepaths_cache[$_plugin_filename] = $_return; + return $_return; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.assign_smarty_interface.php b/include/smarty/internals/core.assign_smarty_interface.php new file mode 100644 index 000000000..7e65a73ec --- /dev/null +++ b/include/smarty/internals/core.assign_smarty_interface.php @@ -0,0 +1,43 @@ + + * Name: assign_smarty_interface
+ * Purpose: assign the $smarty interface variable + * @param array Format: null + * @param Smarty + */ +function smarty_core_assign_smarty_interface($params, &$smarty) +{ + if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) { + return; + } + + $_globals_map = array('g' => 'HTTP_GET_VARS', + 'p' => 'HTTP_POST_VARS', + 'c' => 'HTTP_COOKIE_VARS', + 's' => 'HTTP_SERVER_VARS', + 'e' => 'HTTP_ENV_VARS'); + + $_smarty_vars_request = array(); + + foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) { + if (isset($_globals_map[$_c])) { + $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]); + } + } + $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']); + + $smarty->_smarty_vars['request'] = $_smarty_vars_request; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.create_dir_structure.php b/include/smarty/internals/core.create_dir_structure.php new file mode 100644 index 000000000..999cf5930 --- /dev/null +++ b/include/smarty/internals/core.create_dir_structure.php @@ -0,0 +1,79 @@ +_dir_perms) && !is_dir($_new_dir)) { + $smarty->trigger_error("problem creating directory '" . $_new_dir . "'"); + return false; + } + $_new_dir .= '/'; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.display_debug_console.php b/include/smarty/internals/core.display_debug_console.php new file mode 100644 index 000000000..a5d72913c --- /dev/null +++ b/include/smarty/internals/core.display_debug_console.php @@ -0,0 +1,61 @@ + + * Name: display_debug_console
+ * Purpose: display the javascript debug console window + * @param array Format: null + * @param Smarty + */ +function smarty_core_display_debug_console($params, &$smarty) +{ + // we must force compile the debug template in case the environment + // changed between separate applications. + + if(empty($smarty->debug_tpl)) { + // set path to debug template from SMARTY_DIR + $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl'; + if($smarty->security && is_file($smarty->debug_tpl)) { + $smarty->secure_dir[] = dirname(realpath($smarty->debug_tpl)); + } + $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl'; + } + + $_ldelim_orig = $smarty->left_delimiter; + $_rdelim_orig = $smarty->right_delimiter; + + $smarty->left_delimiter = '{'; + $smarty->right_delimiter = '}'; + + $_compile_id_orig = $smarty->_compile_id; + $smarty->_compile_id = null; + + $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl); + if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path)) + { + ob_start(); + $smarty->_include($_compile_path); + $_results = ob_get_contents(); + ob_end_clean(); + } else { + $_results = ''; + } + + $smarty->_compile_id = $_compile_id_orig; + + $smarty->left_delimiter = $_ldelim_orig; + $smarty->right_delimiter = $_rdelim_orig; + + return $_results; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.get_include_path.php b/include/smarty/internals/core.get_include_path.php new file mode 100644 index 000000000..43432412b --- /dev/null +++ b/include/smarty/internals/core.get_include_path.php @@ -0,0 +1,44 @@ + diff --git a/include/smarty/internals/core.get_microtime.php b/include/smarty/internals/core.get_microtime.php new file mode 100644 index 000000000..f1a28e042 --- /dev/null +++ b/include/smarty/internals/core.get_microtime.php @@ -0,0 +1,23 @@ + diff --git a/include/smarty/internals/core.get_php_resource.php b/include/smarty/internals/core.get_php_resource.php new file mode 100644 index 000000000..786d4e78e --- /dev/null +++ b/include/smarty/internals/core.get_php_resource.php @@ -0,0 +1,80 @@ +trusted_dir; + $smarty->_parse_resource_name($params, $smarty); + + /* + * Find out if the resource exists. + */ + + if ($params['resource_type'] == 'file') { + $_readable = false; + if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) { + $_readable = true; + } else { + // test for file in include_path + $_params = array('file_path' => $params['resource_name']); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_include_path = $_params['new_file_path']; + $_readable = true; + } + } + } else if ($params['resource_type'] != 'file') { + $_template_source = null; + $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0]) + && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0], + array($params['resource_name'], &$_template_source, &$smarty)); + } + + /* + * Set the error function, depending on which class calls us. + */ + if (method_exists($smarty, '_syntax_error')) { + $_error_funcc = '_syntax_error'; + } else { + $_error_funcc = 'trigger_error'; + } + + if ($_readable) { + if ($smarty->security) { + require_once(SMARTY_CORE_DIR . 'core.is_trusted.php'); + if (!smarty_core_is_trusted($params, $smarty)) { + $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted'); + return false; + } + } + } else { + $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable'); + return false; + } + + if ($params['resource_type'] == 'file') { + $params['php_resource'] = $params['resource_name']; + } else { + $params['php_resource'] = $_template_source; + } + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.is_secure.php b/include/smarty/internals/core.is_secure.php new file mode 100644 index 000000000..342f3aff8 --- /dev/null +++ b/include/smarty/internals/core.is_secure.php @@ -0,0 +1,56 @@ +security || $smarty->security_settings['INCLUDE_ANY']) { + return true; + } + + if ($params['resource_type'] == 'file') { + $_rp = realpath($params['resource_name']); + if (isset($params['resource_base_path'])) { + foreach ((array)$params['resource_base_path'] as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false && + strncmp($_rp, $_cd, strlen($_cd)) == 0 && + $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) { + return true; + } + } + } + if (!empty($smarty->secure_dir)) { + foreach ((array)$smarty->secure_dir as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false && + strncmp($_rp, $_cd, strlen($_cd)) == 0 && + $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) { + return true; + } + } + } + } else { + // resource is not on local file system + return call_user_func_array( + $smarty->_plugins['resource'][$params['resource_type']][0][2], + array($params['resource_name'], &$smarty)); + } + + return false; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.is_trusted.php b/include/smarty/internals/core.is_trusted.php new file mode 100644 index 000000000..f0bd2fb8c --- /dev/null +++ b/include/smarty/internals/core.is_trusted.php @@ -0,0 +1,47 @@ +trusted_dir)) { + $_rp = realpath($params['resource_name']); + foreach ((array)$smarty->trusted_dir as $curr_dir) { + if (!empty($curr_dir) && is_readable ($curr_dir)) { + $_cd = realpath($curr_dir); + if (strncmp($_rp, $_cd, strlen($_cd)) == 0 + && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) { + $_smarty_trusted = true; + break; + } + } + } + } + + } else { + // resource is not on local file system + $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3], + array($params['resource_name'], $smarty)); + } + + return $_smarty_trusted; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.load_plugins.php b/include/smarty/internals/core.load_plugins.php new file mode 100644 index 000000000..6db1dc51d --- /dev/null +++ b/include/smarty/internals/core.load_plugins.php @@ -0,0 +1,125 @@ +_plugins[$_type][$_name]; + + /* + * We do not load plugin more than once for each instance of Smarty. + * The following code checks for that. The plugin can also be + * registered dynamically at runtime, in which case template file + * and line number will be unknown, so we fill them in. + * + * The final element of the info array is a flag that indicates + * whether the dynamically registered plugin function has been + * checked for existence yet or not. + */ + if (isset($_plugin)) { + if (empty($_plugin[3])) { + if (!is_callable($_plugin[0])) { + $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } else { + $_plugin[1] = $_tpl_file; + $_plugin[2] = $_tpl_line; + $_plugin[3] = true; + if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */ + } + } + continue; + } else if ($_type == 'insert') { + /* + * For backwards compatibility, we check for insert functions in + * the symbol table before trying to load them as a plugin. + */ + $_plugin_func = 'insert_' . $_name; + if (function_exists($_plugin_func)) { + $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false); + continue; + } + } + + $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name); + + if (! $_found = ($_plugin_file != false)) { + $_message = "could not load plugin file '$_type.$_name.php'\n"; + } + + /* + * If plugin file is found, it -must- provide the properly named + * plugin function. In case it doesn't, simply output the error and + * do not fall back on any other method. + */ + if ($_found) { + include_once $_plugin_file; + + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + continue; + } + } + /* + * In case of insert plugins, their code may be loaded later via + * 'script' attribute. + */ + else if ($_type == 'insert' && $_delayed_loading) { + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + $_found = true; + } + + /* + * Plugin specific processing and error checking. + */ + if (!$_found) { + if ($_type == 'modifier') { + /* + * In case modifier falls back on using PHP functions + * directly, we only allow those specified in the security + * context. + */ + if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) { + $_message = "(secure mode) modifier '$_name' is not allowed"; + } else { + if (!function_exists($_name)) { + $_message = "modifier '$_name' is not implemented"; + } else { + $_plugin_func = $_name; + $_found = true; + } + } + } else if ($_type == 'function') { + /* + * This is a catch-all situation. + */ + $_message = "unknown tag - '$_name'"; + } + } + + if ($_found) { + $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true); + } else { + // output error + $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.load_resource_plugin.php b/include/smarty/internals/core.load_resource_plugin.php new file mode 100644 index 000000000..a7d37d1af --- /dev/null +++ b/include/smarty/internals/core.load_resource_plugin.php @@ -0,0 +1,74 @@ +_plugins['resource'][$params['type']]; + if (isset($_plugin)) { + if (!$_plugin[1] && count($_plugin[0])) { + $_plugin[1] = true; + foreach ($_plugin[0] as $_plugin_func) { + if (!is_callable($_plugin_func)) { + $_plugin[1] = false; + break; + } + } + } + + if (!$_plugin[1]) { + $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__); + } + + return; + } + + $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']); + $_found = ($_plugin_file != false); + + if ($_found) { /* + * If the plugin file is found, it -must- provide the properly named + * plugin functions. + */ + include_once($_plugin_file); + + /* + * Locate functions that we require the plugin to provide. + */ + $_resource_ops = array('source', 'timestamp', 'secure', 'trusted'); + $_resource_funcs = array(); + foreach ($_resource_ops as $_op) { + $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__); + return; + } else { + $_resource_funcs[] = $_plugin_func; + } + } + + $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.process_cached_inserts.php b/include/smarty/internals/core.process_cached_inserts.php new file mode 100644 index 000000000..29cb007eb --- /dev/null +++ b/include/smarty/internals/core.process_cached_inserts.php @@ -0,0 +1,71 @@ +_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis', + $params['results'], $match); + list($cached_inserts, $insert_args) = $match; + + for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) { + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $args = unserialize($insert_args[$i]); + $name = $args['name']; + + if (isset($args['script'])) { + $_params = array('resource_name' => $smarty->_dequote($args['script'])); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + $resource_type = $_params['resource_type']; + $php_resource = $_params['php_resource']; + + + if ($resource_type == 'file') { + $smarty->_include($php_resource, true); + } else { + $smarty->_eval($php_resource); + } + } + + $function_name = $smarty->_plugins['insert'][$name][0]; + if (empty($args['assign'])) { + $replace = $function_name($args, $smarty); + } else { + $smarty->assign($args['assign'], $function_name($args, $smarty)); + $replace = ''; + } + + $params['results'] = str_replace($cached_inserts[$i], $replace, $params['results']); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$name, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time); + } + } + + return $params['results']; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.process_compiled_include.php b/include/smarty/internals/core.process_compiled_include.php new file mode 100644 index 000000000..3e1d4c15a --- /dev/null +++ b/include/smarty/internals/core.process_compiled_include.php @@ -0,0 +1,32 @@ +_cache_including; + $smarty->_cache_including = true; + + $_return = $params['results']; + foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) { + $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s', + array(&$smarty, '_process_compiled_include_callback'), + $_return); + } + $smarty->_cache_including = $_cache_including; + return $_return; +} + +?> diff --git a/include/smarty/internals/core.read_cache_file.php b/include/smarty/internals/core.read_cache_file.php new file mode 100644 index 000000000..ecb147089 --- /dev/null +++ b/include/smarty/internals/core.read_cache_file.php @@ -0,0 +1,111 @@ +force_compile) { + // force compile enabled, always regenerate + return false; + } + + if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) { + list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']]; + return true; + } + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $params['results'] = $smarty->_read_file($_cache_file); + } + + if (empty($params['results'])) { + // nothing to parse (error?), regenerate cache + return false; + } + + $_contents = $params['results']; + $_info_start = strpos($_contents, "\n") + 1; + $_info_len = (int)substr($_contents, 0, $_info_start - 1); + $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len)); + $params['results'] = substr($_contents, $_info_start + $_info_len); + + if ($smarty->caching == 2 && isset ($_cache_info['expires'])){ + // caching by expiration time + if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) { + // cache expired, regenerate + return false; + } + } else { + // caching by lifetime + if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) { + // cache expired, regenerate + return false; + } + } + + if ($smarty->compile_check) { + $_params = array('get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['template']) as $_template_dep) { + $_params['resource_name'] = $_template_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // template file has changed, regenerate cache + return false; + } + } + + if (isset($_cache_info['config'])) { + $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['config']) as $_config_dep) { + $_params['resource_name'] = $_config_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // config file has changed, regenerate cache + return false; + } + } + } + } + + foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { + if (empty($smarty->_cache_serials[$_include_file_path])) { + $smarty->_include($_include_file_path, true); + } + + if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) { + /* regenerate */ + return false; + } + } + $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info); + + $smarty->_cache_info = $_cache_info; + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.rm_auto.php b/include/smarty/internals/core.rm_auto.php new file mode 100644 index 000000000..b251f6491 --- /dev/null +++ b/include/smarty/internals/core.rm_auto.php @@ -0,0 +1,71 @@ + $params['auto_base'], + 'level' => 0, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']); + + if(isset($params['auto_source'])) { + if (isset($params['extensions'])) { + $_res = false; + foreach ((array)$params['extensions'] as $_extension) + $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']); + } else { + $_res = $smarty->_unlink($_tname, $params['exp_time']); + } + } elseif ($smarty->use_sub_dirs) { + $_params = array( + 'dirname' => $_tname, + 'level' => 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + // remove matching file names + $_handle = opendir($params['auto_base']); + $_res = true; + while (false !== ($_filename = readdir($_handle))) { + if($_filename == '.' || $_filename == '..') { + continue; + } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) { + $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']); + } + } + } + } + + return $_res; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.rmdir.php b/include/smarty/internals/core.rmdir.php new file mode 100644 index 000000000..4fdbccc95 --- /dev/null +++ b/include/smarty/internals/core.rmdir.php @@ -0,0 +1,55 @@ + keep root) + * WARNING: no tests, it will try to remove what you tell it! + * + * @param string $dirname + * @param integer $level + * @param integer $exp_time + * @return boolean + */ + +// $dirname, $level = 1, $exp_time = null + +function smarty_core_rmdir($params, &$smarty) +{ + if(!isset($params['level'])) { $params['level'] = 1; } + if(!isset($params['exp_time'])) { $params['exp_time'] = null; } + + if($_handle = @opendir($params['dirname'])) { + + while (false !== ($_entry = readdir($_handle))) { + if ($_entry != '.' && $_entry != '..') { + if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) { + $_params = array( + 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry, + 'level' => $params['level'] + 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + smarty_core_rmdir($_params, $smarty); + } + else { + $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']); + } + } + } + closedir($_handle); + } + + if ($params['level']) { + return @rmdir($params['dirname']); + } + return (bool)$_handle; + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.run_insert_handler.php b/include/smarty/internals/core.run_insert_handler.php new file mode 100644 index 000000000..71c384508 --- /dev/null +++ b/include/smarty/internals/core.run_insert_handler.php @@ -0,0 +1,71 @@ +debugging) { + $_params = array(); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + if ($smarty->caching) { + $_arg_string = serialize($params['args']); + $_name = $params['args']['name']; + if (!isset($smarty->_cache_info['insert_tags'][$_name])) { + $smarty->_cache_info['insert_tags'][$_name] = array('insert', + $_name, + $smarty->_plugins['insert'][$_name][1], + $smarty->_plugins['insert'][$_name][2], + !empty($params['args']['script']) ? true : false); + } + return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5; + } else { + if (isset($params['args']['script'])) { + $_params = array('resource_name' => $smarty->_dequote($params['args']['script'])); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + + if ($_params['resource_type'] == 'file') { + $smarty->_include($_params['php_resource'], true); + } else { + $smarty->_eval($_params['php_resource']); + } + unset($params['args']['script']); + } + + $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0]; + $_content = $_funcname($params['args'], $smarty); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$params['args']['name'], + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + + if (!empty($params['args']["assign"])) { + $smarty->assign($params['args']["assign"], $_content); + } else { + return $_content; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.smarty_include_php.php b/include/smarty/internals/core.smarty_include_php.php new file mode 100644 index 000000000..30c6e7654 --- /dev/null +++ b/include/smarty/internals/core.smarty_include_php.php @@ -0,0 +1,50 @@ + $params['smarty_file']); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + smarty_core_get_php_resource($_params, $smarty); + $_smarty_resource_type = $_params['resource_type']; + $_smarty_php_resource = $_params['php_resource']; + + if (!empty($params['smarty_assign'])) { + ob_start(); + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + $smarty->assign($params['smarty_assign'], ob_get_contents()); + ob_end_clean(); + } else { + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + } +} + + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.write_cache_file.php b/include/smarty/internals/core.write_cache_file.php new file mode 100644 index 000000000..72f785b74 --- /dev/null +++ b/include/smarty/internals/core.write_cache_file.php @@ -0,0 +1,96 @@ +_cache_info['timestamp'] = time(); + if ($smarty->cache_lifetime > -1){ + // expiration set + $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime; + } else { + // cache will never expire + $smarty->_cache_info['expires'] = -1; + } + + // collapse nocache.../nocache-tags + if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) { + // remove everything between every pair of outermost noache.../nocache-tags + // and replace it by a single nocache-tag + // this new nocache-tag will be replaced by dynamic contents in + // smarty_core_process_compiled_includes() on a cache-read + + $match_count = count($match[0]); + $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE); + + $level = 0; + $j = 0; + for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) { + if ($results[$i] == $match[0][$j]) { + // nocache tag + if ($match[1][$j]) { // closing tag + $level--; + unset($results[$i]); + } else { // opening tag + if ($level++ > 0) unset($results[$i]); + } + $j++; + } elseif ($level > 0) { + unset($results[$i]); + } + } + $params['results'] = implode('', $results); + } + $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials; + + // prepend the cache header info into cache file + $_cache_info = serialize($smarty->_cache_info); + $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results']; + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + + if(!@is_writable($smarty->cache_dir)) { + // cache_dir not writable, see if it exists + if(!@is_dir($smarty->cache_dir)) { + $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.write_compiled_include.php b/include/smarty/internals/core.write_compiled_include.php new file mode 100644 index 000000000..5e0b2e0dd --- /dev/null +++ b/include/smarty/internals/core.write_compiled_include.php @@ -0,0 +1,91 @@ +caching && \!\$this->_cache_including\) \{ echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\';\}'; + $_tag_end = 'if \(\$this->caching && \!\$this->_cache_including\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}'; + + preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us', + $params['compiled_content'], $_match_source, PREG_SET_ORDER); + + // no nocache-parts found: done + if (count($_match_source)==0) return; + + // convert the matched php-code to functions + $_include_compiled = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $_include_compiled .= " compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n"; + + $_compile_path = $params['include_file_path']; + + $smarty->_cache_serials[$_compile_path] = $params['cache_serial']; + $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>"; + + $_include_compiled .= $params['plugins_code']; + $_include_compiled .= "= 5.0) ? '_smarty' : 'this'; + for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) { + $_match =& $_match_source[$_i]; + $source = $_match[4]; + if ($this_varname == '_smarty') { + /* rename $this to $_smarty in the sourcecode */ + $tokens = token_get_all('\n"; + + $_params = array('filename' => $_compile_path, + 'contents' => $_include_compiled, 'create_dirs' => true); + + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + + +?> diff --git a/include/smarty/internals/core.write_compiled_resource.php b/include/smarty/internals/core.write_compiled_resource.php new file mode 100644 index 000000000..b902eff3c --- /dev/null +++ b/include/smarty/internals/core.write_compiled_resource.php @@ -0,0 +1,35 @@ +compile_dir)) { + // compile_dir not writable, see if it exists + if(!@is_dir($smarty->compile_dir)) { + $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/internals/core.write_file.php b/include/smarty/internals/core.write_file.php new file mode 100644 index 000000000..09e169840 --- /dev/null +++ b/include/smarty/internals/core.write_file.php @@ -0,0 +1,54 @@ + $_dirname); + require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php'); + smarty_core_create_dir_structure($_params, $smarty); + } + + // write to tmp file, then rename it to avoid + // file locking race condition + $_tmp_file = tempnam($_dirname, 'wrt'); + + if (!($fd = @fopen($_tmp_file, 'wb'))) { + $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt'); + if (!($fd = @fopen($_tmp_file, 'wb'))) { + $smarty->trigger_error("problem writing temporary file '$_tmp_file'"); + return false; + } + } + + fwrite($fd, $params['contents']); + fclose($fd); + + // Delete the file if it allready exists (this is needed on Win, + // because it cannot overwrite files with rename() + if (file_exists($params['filename'])) { + @unlink($params['filename']); + } + @rename($_tmp_file, $params['filename']); + @chmod($params['filename'], $smarty->_file_perms); + + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/block.t.php b/include/smarty/plugins/block.t.php new file mode 100644 index 000000000..dc5cf4298 --- /dev/null +++ b/include/smarty/plugins/block.t.php @@ -0,0 +1,146 @@ + + * @param string $language override global t_language variable + * @version: 1.3 + */ +function smarty_block_t($params, $content, &$this) +{ + if (!$content) return $content; + // Setup local development variables. + // If $development = false then use_babelfish is ignored. + $development = false; + // If use_babelfish is false, placeholders will be put in .po files + // but no translation will be attempted using babelfish. + $use_babelfish = false; + + global $t_language, $t_language_from, $t_msgfmt_location, $t_gettext_message_dir; + + // Check for new language + if (isset($params['language']) && $params['language']) { + $t_language = $params['language']; + putenv ("LC_ALL={$GLOBALS[t_language]}"); + } + + // If under development, check for necessary files + if ($development) { + // Translate string once for every language supported + foreach ($GLOBALS['t_language_all'] as $t_language) { + // Check for language directory; create if necessary + if (!is_dir($t_gettext_message_dir . $t_language)) { + mkdir ($t_gettext_message_dir . $t_language); + mkdir ("$t_gettext_message_dir$t_language/LC_MESSAGES"); + } + // Check for .po file + $po = "$t_gettext_message_dir$t_language/LC_MESSAGES/messages.po"; + if (!file_exists($po)) _create_po_file($po); + + // Load the .po file and check for the current translation string + $text = file($po); + $cst_content = addcslashes(trim($content), '\\"'); + if (!_in_array_trim('msgid "' . $cst_content . '"', $text)) { + // String is not in translation file; add it + // Get translated string from babelfish if set to true + if ($use_babelfish) { + $translated = ''; + $url ="http://babelfish.altavista.com/babelfish/tr?lp={$t_language_from}_{$t_language}&intl=1&tt=urltext&doit=done&urltext=" . urlencode(htmlspecialchars($content, ENT_NOQUOTES, 'UTF-8')); + $fp = fopen($url, 'r'); + // Find the translated string + //foreach ($babel as $line) { + while ($line = fgets($fp)) { + if (strstr($line, "lang=$t_language")) { + // multibytes do not work yet with + // html_entity_decode but that is ok, + // since altavista does not seem to send entities. + $translated = html_entity_decode(trim(addcslashes(strip_tags($line), '\\"')), ENT_NOQUOTES); + + break; + } + } + fclose($fp); + unset($url); + } + + // Add string to .po + // mark translation as babelfish, so we know + // that we need to look after it. + if ($use_babelfish) { + error_log("#: babelfish\n", 3, $po); + } + error_log("#: " . $this->_plugins['block']['t'][1] . "\nmsgid \"" . $cst_content . "\"\nmsgstr \"$translated\"\n\n", 3, $po); + + // Recompile translation file + `$t_msgfmt_location -o $t_gettext_message_dir$t_language/LC_MESSAGES/messages.mo $po`; + } + } + } + // Do the actual translation through gettext. + bindtextdomain ('messages', $t_gettext_message_dir); + return gettext(trim($content)); +} + +// Helper functions +function _in_array_trim($needle, $haystack) { + $needle = trim($needle); + foreach ($haystack as $ck) { + if ($needle == trim($ck)) return true; + } + return false; +} + +function _create_po_file($po) { + touch ($po); + // put header info for .po file + $year = date('Y'); + $date = date('r'); + $body = << diff --git a/include/smarty/plugins/block.textformat.php b/include/smarty/plugins/block.textformat.php new file mode 100644 index 000000000..aaebab2f5 --- /dev/null +++ b/include/smarty/plugins/block.textformat.php @@ -0,0 +1,102 @@ + + * Name: textformat
+ * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * @param array + *
+ * Params:   style: string (email)
+ *           indent: integer (0)
+ *           wrap: integer (80)
+ *           wrap_char string ("\n")
+ *           indent_char: string (" ")
+ *           wrap_boundary: boolean (true)
+ * 
+ * @param string contents of the block + * @param Smarty clever simulation of a method + * @return string string $content re-formatted + */ +function smarty_block_textformat($params, $content, &$smarty) +{ + if (is_null($content)) { + return; + } + + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string)$_val; + break; + + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int)$_val; + break; + + case 'wrap_cut': + $$_key = (bool)$_val; + break; + + default: + $smarty->trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + + // split into paragraphs + $_paragraphs = preg_split('![\r\n][\r\n]!',$content); + $_output = ''; + + for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { + if ($_paragraphs[$_x] == '') { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]); + // indent first line + if($indent_first > 0) { + $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; + } + // wordwrap sentences + $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); + // indent lines + if($indent > 0) { + $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + return $assign ? $smarty->assign($assign, $_output) : $_output; + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/compiler.assign.php b/include/smarty/plugins/compiler.assign.php new file mode 100644 index 000000000..2e0201779 --- /dev/null +++ b/include/smarty/plugins/compiler.assign.php @@ -0,0 +1,38 @@ + + * Name: assign
+ * Purpose: assign a value to a template variable + * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign} + * (Smarty online manual) + * @param string containing var-attribute and value-attribute + * @param Smarty_Compiler + */ +function smarty_compiler_assign($tag_attrs, &$compiler) +{ + $_params = $compiler->_parse_attrs($tag_attrs); + + if (!isset($_params['var'])) { + $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING); + return; + } + + if (!isset($_params['value'])) { + $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING); + return; + } + + return "\$this->assign({$_params['var']}, {$_params['value']});"; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.assign.php b/include/smarty/plugins/function.assign.php new file mode 100644 index 000000000..ad23f043d --- /dev/null +++ b/include/smarty/plugins/function.assign.php @@ -0,0 +1,38 @@ + + * Name: assign
+ * Purpose: assign a value to a template variable + * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign} + * (Smarty online manual) + * @param array Format: array('var' => variable name, 'value' => value to assign) + * @param Smarty + */ +function smarty_function_assign($params, &$smarty) +{ + extract($params); + + if (empty($var)) { + $smarty->trigger_error("assign: missing 'var' parameter"); + return; + } + + if (!in_array('value', array_keys($params))) { + $smarty->trigger_error("assign: missing 'value' parameter"); + return; + } + + $smarty->assign($var, $value); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.assign_debug_info.php b/include/smarty/plugins/function.assign_debug_info.php new file mode 100644 index 000000000..8015624b1 --- /dev/null +++ b/include/smarty/plugins/function.assign_debug_info.php @@ -0,0 +1,39 @@ + + * Name: assign_debug_info
+ * Purpose: assign debug info to the template
+ * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, + * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} + * @param Smarty + */ +function smarty_function_assign_debug_info($params, &$smarty) +{ + $assigned_vars = $smarty->_tpl_vars; + ksort($assigned_vars); + if (@is_array($smarty->_config[0])) { + $config_vars = $smarty->_config[0]; + ksort($config_vars); + $smarty->assign("_debug_config_keys", array_keys($config_vars)); + $smarty->assign("_debug_config_vals", array_values($config_vars)); + } + + $included_templates = $smarty->_smarty_debug_info; + + $smarty->assign("_debug_keys", array_keys($assigned_vars)); + $smarty->assign("_debug_vals", array_values($assigned_vars)); + + $smarty->assign("_debug_tpls", $included_templates); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.config_load.php b/include/smarty/plugins/function.config_load.php new file mode 100644 index 000000000..db7f8f6b9 --- /dev/null +++ b/include/smarty/plugins/function.config_load.php @@ -0,0 +1,140 @@ + + * Name: config_load
+ * Purpose: load config file vars + * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load} + * (Smarty online manual) + * @param array Format: + *
+ * array('file' => required config file name,
+ *       'section' => optional config file section to load
+ *       'scope' => local/parent/global
+ *       'global' => overrides scope, setting to parent if true)
+ * 
+ * @param Smarty + */ +function smarty_function_config_load($params, &$smarty) +{ + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null; + $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null; + $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global'; + $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false; + + if (!isset($_file) || strlen($_file) == 0) { + $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__); + } + + if (isset($_scope)) { + if ($_scope != 'local' && + $_scope != 'parent' && + $_scope != 'global') { + $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } else { + if ($_global) { + $_scope = 'parent'; + } else { + $_scope = 'local'; + } + } + + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + 'get_source' => false); + $smarty->_parse_resource_name($_params); + $_file_path = $_params['resource_type'] . ':' . $_params['resource_name']; + if (isset($_section)) + $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section); + else + $_compile_file = $smarty->_get_compile_path($_file_path); + + if($smarty->force_compile || !file_exists($_compile_file)) { + $_compile = true; + } elseif ($smarty->compile_check) { + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + 'get_source' => false); + $_compile = $smarty->_fetch_resource_info($_params) && + $_params['resource_timestamp'] > filemtime($_compile_file); + } else { + $_compile = false; + } + + if($_compile) { + // compile config file + if(!is_object($smarty->_conf_obj)) { + require_once SMARTY_DIR . $smarty->config_class . '.class.php'; + $smarty->_conf_obj = new $smarty->config_class(); + $smarty->_conf_obj->overwrite = $smarty->config_overwrite; + $smarty->_conf_obj->booleanize = $smarty->config_booleanize; + $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden; + $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines; + } + + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + $_params['get_source'] = true); + if (!$smarty->_fetch_resource_info($_params)) { + return; + } + $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']); + $_config_vars = array_merge($smarty->_conf_obj->get($_file), + $smarty->_conf_obj->get($_file, $_section)); + if(function_exists('var_export')) { + $_output = ''; + } else { + $_output = ''\\\'', '\\'=>'\\\\')) . '\'); ?>'; + } + $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp'])); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $smarty); + } else { + include($_compile_file); + } + + if ($smarty->caching) { + $smarty->_cache_info['config'][$_file] = true; + } + + $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars); + $smarty->_config[0]['files'][$_file] = true; + + if ($_scope == 'parent') { + $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars); + $smarty->_config[1]['files'][$_file] = true; + } else if ($_scope == 'global') { + for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) { + $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars); + $smarty->_config[$i]['files'][$_file] = true; + } + } + + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'config', + 'filename' => $_file.' ['.$_section.'] '.$_scope, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.counter.php b/include/smarty/plugins/function.counter.php new file mode 100644 index 000000000..cfe5dd886 --- /dev/null +++ b/include/smarty/plugins/function.counter.php @@ -0,0 +1,79 @@ + + * Name: counter
+ * Purpose: print out a counter value + * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * @param array parameters + * @param Smarty + * @return string|null + */ +function smarty_function_counter($params, &$smarty) +{ + static $counters = array(); + + $name = (isset($params['name'])) ? $params['name'] : 'default'; + if (!isset($counters[$name])) { + $counters[$name] = array( + 'start'=>1, + 'skip'=>1, + 'direction'=>'up', + 'count'=>1 + ); + } + $counter =& $counters[$name]; + + if (isset($params['start'])) { + $counter['start'] = $counter['count'] = (int)$params['start']; + } + + if (!empty($params['assign'])) { + $counter['assign'] = $params['assign']; + } + + if (isset($counter['assign'])) { + $smarty->assign($counter['assign'], $counter['count']); + } + + if (isset($params['print'])) { + $print = (bool)$params['print']; + } else { + $print = empty($counter['assign']); + } + + if ($print) { + $retval = $counter['count']; + } else { + $retval = null; + } + + if (isset($params['skip'])) { + $counter['skip'] = $params['skip']; + } + + if (isset($params['direction'])) { + $counter['direction'] = $params['direction']; + } + + if ($counter['direction'] == "down") + $counter['count'] -= $counter['skip']; + else + $counter['count'] += $counter['skip']; + + return $retval; + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.cycle.php b/include/smarty/plugins/function.cycle.php new file mode 100644 index 000000000..fe78bb87d --- /dev/null +++ b/include/smarty/plugins/function.cycle.php @@ -0,0 +1,102 @@ + + * Name: cycle
+ * Date: May 3, 2002
+ * Purpose: cycle through given values
+ * Input: + * - name = name of cycle (optional) + * - values = comma separated list of values to cycle, + * or an array of values to cycle + * (this can be left out for subsequent calls) + * - reset = boolean - resets given var to true + * - print = boolean - print var or not. default is true + * - advance = boolean - whether or not to advance the cycle + * - delimiter = the value delimiter, default is "," + * - assign = boolean, assigns to template var instead of + * printed. + * + * Examples:
+ *
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * 
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * @param array + * @param Smarty + * @return string|null + */ +function smarty_function_cycle($params, &$smarty) +{ + static $cycle_vars; + + $name = (empty($params['name'])) ? 'default' : $params['name']; + $print = (isset($params['print'])) ? (bool)$params['print'] : true; + $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; + $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; + + if (!in_array('values', array_keys($params))) { + if(!isset($cycle_vars[$name]['values'])) { + $smarty->trigger_error("cycle: missing 'values' parameter"); + return; + } + } else { + if(isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $params['values'] ) { + $cycle_vars[$name]['index'] = 0; + } + $cycle_vars[$name]['values'] = $params['values']; + } + + $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ','; + + if(is_array($cycle_vars[$name]['values'])) { + $cycle_array = $cycle_vars[$name]['values']; + } else { + $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + } + + if(!isset($cycle_vars[$name]['index']) || $reset ) { + $cycle_vars[$name]['index'] = 0; + } + + if (isset($params['assign'])) { + $print = false; + $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); + } + + if($print) { + $retval = $cycle_array[$cycle_vars[$name]['index']]; + } else { + $retval = null; + } + + if($advance) { + if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { + $cycle_vars[$name]['index'] = 0; + } else { + $cycle_vars[$name]['index']++; + } + } + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.debug.php b/include/smarty/plugins/function.debug.php new file mode 100644 index 000000000..43452307b --- /dev/null +++ b/include/smarty/plugins/function.debug.php @@ -0,0 +1,35 @@ + + * Name: debug
+ * Date: July 1, 2002
+ * Purpose: popup debug window + * @link http://smarty.php.net/manual/en/language.function.debug.php {debug} + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string output from {@link Smarty::_generate_debug_output()} + */ +function smarty_function_debug($params, &$smarty) +{ + if (isset($params['output'])) { + $smarty->assign('_smarty_debug_output', $params['output']); + } + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + return smarty_core_display_debug_console(null, $smarty); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.eval.php b/include/smarty/plugins/function.eval.php new file mode 100644 index 000000000..3a4b8b2b8 --- /dev/null +++ b/include/smarty/plugins/function.eval.php @@ -0,0 +1,48 @@ + + * Name: eval
+ * Purpose: evaluate a template variable as a template
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval} + * (Smarty online manual) + * @param array + * @param Smarty + */ +function smarty_function_eval($params, &$smarty) +{ + + if (!isset($params['var'])) { + $smarty->trigger_error("eval: missing 'var' parameter"); + return; + } + + if($params['var'] == '') { + return; + } + + $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled); + + ob_start(); + $smarty->_eval('?>' . $_var_compiled); + $_contents = ob_get_contents(); + ob_end_clean(); + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'], $_contents); + } else { + return $_contents; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.fetch.php b/include/smarty/plugins/function.fetch.php new file mode 100644 index 000000000..f5a6987a9 --- /dev/null +++ b/include/smarty/plugins/function.fetch.php @@ -0,0 +1,220 @@ + + * Name: fetch
+ * Purpose: fetch file, web or ftp data and display results + * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string|null if the assign parameter is passed, Smarty assigns the + * result to a template variable + */ +function smarty_function_fetch($params, &$smarty) +{ + if (empty($params['file'])) { + $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty"); + return; + } + + $content = ''; + if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) { + $_params = array('resource_type' => 'file', 'resource_name' => $params['file']); + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if(!smarty_core_is_secure($_params, $smarty)) { + $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed'); + return; + } + + // fetch the file + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\''); + return; + } + } else { + // not a local file + if(preg_match('!^http://!i',$params['file'])) { + // http fetch + if($uri_parts = parse_url($params['file'])) { + // set defaults + $host = $server_name = $uri_parts['host']; + $timeout = 30; + $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + $agent = "Smarty Template Engine ".$smarty->_version; + $referer = ""; + $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; + $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; + $_is_proxy = false; + if(empty($uri_parts['port'])) { + $port = 80; + } else { + $port = $uri_parts['port']; + } + if(!empty($uri_parts['user'])) { + $user = $uri_parts['user']; + } + if(!empty($uri_parts['pass'])) { + $pass = $uri_parts['pass']; + } + // loop through parameters, setup headers + foreach($params as $param_key => $param_value) { + switch($param_key) { + case "file": + case "assign": + case "assign_headers": + break; + case "user": + if(!empty($param_value)) { + $user = $param_value; + } + break; + case "pass": + if(!empty($param_value)) { + $pass = $param_value; + } + break; + case "accept": + if(!empty($param_value)) { + $accept = $param_value; + } + break; + case "header": + if(!empty($param_value)) { + if(!preg_match('![\w\d-]+: .+!',$param_value)) { + $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'"); + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case "proxy_host": + if(!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case "proxy_port": + if(!preg_match('!\D!', $param_value)) { + $proxy_port = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + case "agent": + if(!empty($param_value)) { + $agent = $param_value; + } + break; + case "referer": + if(!empty($param_value)) { + $referer = $param_value; + } + break; + case "timeout": + if(!preg_match('!\D!', $param_value)) { + $timeout = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + default: + $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'"); + return; + } + } + if(!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + } else { + $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + } + + if(!$fp) { + $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)"); + return; + } else { + if($_is_proxy) { + fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if(!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if(!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if(!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if(!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if(isset($extra_headers) && is_array($extra_headers)) { + foreach($extra_headers as $curr_header) { + fputs($fp, $curr_header."\r\n"); + } + } + if(!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); + } + + fputs($fp, "\r\n"); + while(!feof($fp)) { + $content .= fgets($fp,4096); + } + fclose($fp); + $csplit = split("\r\n\r\n",$content,2); + + $content = $csplit[1]; + + if(!empty($params['assign_headers'])) { + $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0])); + } + } + } else { + $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax"); + return; + } + } else { + // ftp fetch + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\''); + return; + } + } + + } + + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'],$content); + } else { + return $content; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.html_checkboxes.php b/include/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 000000000..ed8ad7f33 --- /dev/null +++ b/include/smarty/plugins/function.html_checkboxes.php @@ -0,0 +1,143 @@ + + * Type: function
+ * Name: html_checkboxes
+ * Date: 24.Feb.2003
+ * Purpose: Prints out a list of checkbox input types
+ * Input:
+ * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * Examples: + *
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='
' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} + *
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_checkboxes($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $name = 'checkbox'; + $values = null; + $options = null; + $selected = null; + $separator = ''; + $labels = true; + $output = null; + + $extra = ''; + + foreach($params as $_key => $_val) { + switch($_key) { + case 'name': + case 'separator': + $$_key = $_val; + break; + + case 'labels': + $$_key = (bool)$_val; + break; + + case 'options': + $$_key = (array)$_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + + case 'checked': + case 'selected': + $selected = array_map('strval', array_values((array)$_val)); + break; + + case 'checkboxes': + $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array)$_val; + break; + + case 'assign': + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + settype($selected, 'array'); + $_html_result = array(); + + if (isset($options)) { + + foreach ($options as $_key=>$_val) + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + + } else { + foreach ($values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + if(!empty($params['assign'])) { + $smarty->assign($params['assign'], $_html_result); + } else { + return implode("\n",$_html_result); + } + +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) $_output .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/include/smarty/plugins/function.html_image.php b/include/smarty/plugins/function.html_image.php new file mode 100644 index 000000000..c62b0fea6 --- /dev/null +++ b/include/smarty/plugins/function.html_image.php @@ -0,0 +1,139 @@ + + * Name: html_image
+ * Date: Feb 24, 2003
+ * Purpose: format HTML tags for the image
+ * Input:
+ * - file = file (and path) of image (required) + * - height = image height (optional, default actual height) + * - width = image width (optional, default actual width) + * - basedir = base directory for absolute paths, default + * is environment variable DOCUMENT_ROOT + * + * Examples: {html_image file="images/masthead.gif"} + * Output: + * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image} + * (Smarty online manual) + * @author Monte Ohrt + * @author credits to Duda - wrote first image function + * in repository, helped with lots of functionality + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_image($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $alt = ''; + $file = ''; + $height = ''; + $width = ''; + $extra = ''; + $prefix = ''; + $suffix = ''; + $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : ''; + foreach($params as $_key => $_val) { + switch($_key) { + case 'file': + case 'height': + case 'width': + case 'dpi': + case 'basedir': + $$_key = $_val; + break; + + case 'alt': + if(!is_array($_val)) { + $$_key = smarty_function_escape_special_chars($_val); + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + + case 'link': + case 'href': + $prefix = ''; + $suffix = ''; + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (empty($file)) { + $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE); + return; + } + + if (substr($file,0,1) == '/') { + $_image_path = $basedir . $file; + } else { + $_image_path = $file; + } + + if(!isset($params['width']) || !isset($params['height'])) { + if ($smarty->security && + ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) && + (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) && + (!smarty_core_is_secure($_params, $smarty)) ) { + $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE); + + } elseif (!$_image_data = @getimagesize($_image_path)) { + if(!file_exists($_image_path)) { + $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE); + return; + } else if(!is_readable($_image_path)) { + $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE); + return; + } else { + $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE); + return; + } + } + + if(!isset($params['width'])) { + $width = $_image_data[0]; + } + if(!isset($params['height'])) { + $height = $_image_data[1]; + } + + } + + if(isset($params['dpi'])) { + if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) { + $dpi_default = 72; + } else { + $dpi_default = 96; + } + $_resize = $dpi_default/$params['dpi']; + $width = round($width * $_resize); + $height = round($height * $_resize); + } + + return $prefix . ''.$alt.'' . $suffix; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.html_options.php b/include/smarty/plugins/function.html_options.php new file mode 100644 index 000000000..ae864f732 --- /dev/null +++ b/include/smarty/plugins/function.html_options.php @@ -0,0 +1,121 @@ + + * Name: html_options
+ * Input:
+ * - name (optional) - string default "select" + * - values (required if no options supplied) - array + * - options (required if no values supplied) - associative array + * - selected (optional) - string default not set + * - output (required if not options supplied) - array + * Purpose: Prints the list of ' . "\n"; + foreach ($values as $key => $value) { + $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected); + } + $optgroup_html .= "\n"; + return $optgroup_html; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.html_radios.php b/include/smarty/plugins/function.html_radios.php new file mode 100644 index 000000000..dc7baee84 --- /dev/null +++ b/include/smarty/plugins/function.html_radios.php @@ -0,0 +1,150 @@ + + * Type: function
+ * Name: html_radios
+ * Date: 24.Feb.2003
+ * Purpose: Prints out a list of radio input types
+ * Input:
+ * - name (optional) - string default "radio" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
or   + * - output (optional) - the output next to each radio button + * - assign (optional) - assign the output as an array to this variable + * Examples: + *
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='
' output=$names} + * {html_radios values=$ids checked=$checked separator='
' output=$names} + *
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_radios($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $name = 'radio'; + $values = null; + $options = null; + $selected = null; + $separator = ''; + $labels = true; + $output = null; + $extra = ''; + + foreach($params as $_key => $_val) { + switch($_key) { + case 'name': + case 'separator': + $$_key = (string)$_val; + break; + + case 'checked': + case 'selected': + if(is_array($_val)) { + $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING); + } else { + $selected = (string)$_val; + } + break; + + case 'labels': + $$_key = (bool)$_val; + break; + + case 'options': + $$_key = (array)$_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + + case 'radios': + $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array)$_val; + break; + + case 'assign': + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + $_html_result = array(); + + if (isset($options)) { + + foreach ($options as $_key=>$_val) + $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + } else { + + foreach ($values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + if(!empty($params['assign'])) { + $smarty->assign($params['assign'], $_html_result); + } else { + return implode("\n",$_html_result); + } + +} + +function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) { + $_id = smarty_function_escape_special_chars($name . '_' . $value); + $_output .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/include/smarty/plugins/function.html_select_date.php b/include/smarty/plugins/function.html_select_date.php new file mode 100644 index 000000000..fc2d449a8 --- /dev/null +++ b/include/smarty/plugins/function.html_select_date.php @@ -0,0 +1,316 @@ + + * Name: html_select_date
+ * Purpose: Prints the dropdowns for date selection. + * + * ChangeLog:
+ * - 1.0 initial release + * - 1.1 added support for +/- N syntax for begin + * and end year values. (Monte) + * - 1.2 added support for yyyy-mm-dd syntax for + * time value. (Jan Rosier) + * - 1.3 added support for choosing format for + * month values (Gary Loescher) + * - 1.3.1 added support for choosing format for + * day values (Marcus Bointon) + * - 1.3.2 suppport negative timestamps, force year + * dropdown to include given date unless explicitly set (Monte) + * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date} + * (Smarty online manual) + * @version 1.3.2 + * @author Andrei Zmievski + * @param array + * @param Smarty + * @return string + */ +function smarty_function_html_select_date($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','make_timestamp'); + require_once $smarty->_get_plugin_filepath('function','html_options'); + /* Default values. */ + $prefix = "Date_"; + $start_year = strftime("%Y"); + $end_year = $start_year; + $display_days = true; + $display_months = true; + $display_years = true; + $month_format = "%B"; + /* Write months as numbers by default GL */ + $month_value_format = "%m"; + $day_format = "%02d"; + /* Write day values using this format MB */ + $day_value_format = "%d"; + $year_as_text = false; + /* Display years in reverse order? Ie. 2000,1999,.... */ + $reverse_years = false; + /* Should the select boxes be part of an array when returned from PHP? + e.g. setting it to "birthday", would create "birthday[Day]", + "birthday[Month]" & "birthday[Year]". Can be combined with prefix */ + $field_array = null; + /* tags. + If not set, uses default dropdown. */ + $day_size = null; + $month_size = null; + $year_size = null; + /* Unparsed attributes common to *ALL* the tags. + An example might be in the template: all_extra ='class ="foo"'. */ + $all_extra = null; + /* Separate attributes for the tags. */ + $day_extra = null; + $month_extra = null; + $year_extra = null; + /* Order in which to display the fields. + "D" -> day, "M" -> month, "Y" -> year. */ + $field_order = 'MDY'; + /* String printed between the different fields. */ + $field_separator = "\n"; + $time = time(); + $all_empty = null; + $day_empty = null; + $month_empty = null; + $year_empty = null; + + foreach ($params as $_key=>$_value) { + switch ($_key) { + case 'prefix': + case 'time': + case 'start_year': + case 'end_year': + case 'month_format': + case 'day_format': + case 'day_value_format': + case 'field_array': + case 'day_size': + case 'month_size': + case 'year_size': + case 'all_extra': + case 'day_extra': + case 'month_extra': + case 'year_extra': + case 'field_order': + case 'field_separator': + case 'month_value_format': + case 'month_empty': + case 'day_empty': + case 'year_empty': + $$_key = (string)$_value; + break; + + case 'all_empty': + $$_key = (string)$_value; + $day_empty = $month_empty = $year_empty = $all_empty; + break; + + case 'display_days': + case 'display_months': + case 'display_years': + case 'year_as_text': + case 'reverse_years': + $$_key = (bool)$_value; + break; + + default: + $smarty->trigger_error("[html_select_date] unknown parameter $_key", E_USER_WARNING); + + } + } + + if(preg_match('!^-\d+$!',$time)) { + // negative timestamp, use date() + $time = date('Y-m-d',$time); + } + // If $time is not in format yyyy-mm-dd + if (!preg_match('/^\d{0,4}-\d{0,2}-\d{0,2}$/', $time)) { + // use smarty_make_timestamp to get an unix timestamp and + // strftime to make yyyy-mm-dd + $time = strftime('%Y-%m-%d', smarty_make_timestamp($time)); + } + // Now split this in pieces, which later can be used to set the select + $time = explode("-", $time); + + // make syntax "+N" or "-N" work with start_year and end_year + if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) { + if ($match[1] == '+') { + $end_year = strftime('%Y') + $match[2]; + } else { + $end_year = strftime('%Y') - $match[2]; + } + } + if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) { + if ($match[1] == '+') { + $start_year = strftime('%Y') + $match[2]; + } else { + $start_year = strftime('%Y') - $match[2]; + } + } + if (strlen($time[0]) > 0) { + if ($start_year > $time[0] && !isset($params['start_year'])) { + // force start year to include given date if not explicitly set + $start_year = $time[0]; + } + if($end_year < $time[0] && !isset($params['end_year'])) { + // force end year to include given date if not explicitly set + $end_year = $time[0]; + } + } + + $field_order = strtoupper($field_order); + + $html_result = $month_result = $day_result = $year_result = ""; + + if ($display_months) { + $month_names = array(); + $month_values = array(); + if(isset($month_empty)) { + $month_names[''] = $month_empty; + $month_values[''] = ''; + } + for ($i = 1; $i <= 12; $i++) { + $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000)); + $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000)); + } + + $month_result .= ''; + } + + if ($display_days) { + $days = array(); + if (isset($day_empty)) { + $days[''] = $day_empty; + $day_values[''] = ''; + } + for ($i = 1; $i <= 31; $i++) { + $days[] = sprintf($day_format, $i); + $day_values[] = sprintf($day_value_format, $i); + } + + $day_result .= ''; + } + + if ($display_years) { + if (null !== $field_array){ + $year_name = $field_array . '[' . $prefix . 'Year]'; + } else { + $year_name = $prefix . 'Year'; + } + if ($year_as_text) { + $year_result .= ' $years, + 'values' => $yearvals, + 'selected' => $time[0], + 'print_result' => false), + $smarty); + $year_result .= ''; + } + } + + // Loop thru the field_order field + for ($i = 0; $i <= 2; $i++){ + $c = substr($field_order, $i, 1); + switch ($c){ + case 'D': + $html_result .= $day_result; + break; + + case 'M': + $html_result .= $month_result; + break; + + case 'Y': + $html_result .= $year_result; + break; + } + // Add the field seperator + if($i != 2) { + $html_result .= $field_separator; + } + } + + return $html_result; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.html_select_time.php b/include/smarty/plugins/function.html_select_time.php new file mode 100644 index 000000000..00cd1ae88 --- /dev/null +++ b/include/smarty/plugins/function.html_select_time.php @@ -0,0 +1,192 @@ + + * Name: html_select_time
+ * Purpose: Prints the dropdowns for time selection + * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + * @uses smarty_make_timestamp() + */ +function smarty_function_html_select_time($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','make_timestamp'); + require_once $smarty->_get_plugin_filepath('function','html_options'); + /* Default values. */ + $prefix = "Time_"; + $time = time(); + $display_hours = true; + $display_minutes = true; + $display_seconds = true; + $display_meridian = true; + $use_24_hours = true; + $minute_interval = 1; + $second_interval = 1; + /* Should the select boxes be part of an array when returned from PHP? + e.g. setting it to "birthday", would create "birthday[Hour]", + "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]". + Can be combined with prefix. */ + $field_array = null; + $all_extra = null; + $hour_extra = null; + $minute_extra = null; + $second_extra = null; + $meridian_extra = null; + + foreach ($params as $_key=>$_value) { + switch ($_key) { + case 'prefix': + case 'time': + case 'field_array': + case 'all_extra': + case 'hour_extra': + case 'minute_extra': + case 'second_extra': + case 'meridian_extra': + $$_key = (string)$_value; + break; + + case 'display_hours': + case 'display_minutes': + case 'display_seconds': + case 'display_meridian': + case 'use_24_hours': + $$_key = (bool)$_value; + break; + + case 'minute_interval': + case 'second_interval': + $$_key = (int)$_value; + break; + + default: + $smarty->trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING); + } + } + + $time = smarty_make_timestamp($time); + + $html_result = ''; + + if ($display_hours) { + $hours = $use_24_hours ? range(0, 23) : range(1, 12); + $hour_fmt = $use_24_hours ? '%H' : '%I'; + for ($i = 0, $for_max = count($hours); $i < $for_max; $i++) + $hours[$i] = sprintf('%02d', $hours[$i]); + $html_result .= '\n"; + } + + if ($display_minutes) { + $all_minutes = range(0, 59); + for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval) + $minutes[] = sprintf('%02d', $all_minutes[$i]); + $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval); + $html_result .= '\n"; + } + + if ($display_seconds) { + $all_seconds = range(0, 59); + for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval) + $seconds[] = sprintf('%02d', $all_seconds[$i]); + $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval); + $html_result .= '\n"; + } + + if ($display_meridian && !$use_24_hours) { + $html_result .= '\n"; + } + + return $html_result; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.html_table.php b/include/smarty/plugins/function.html_table.php new file mode 100644 index 000000000..62d7410b8 --- /dev/null +++ b/include/smarty/plugins/function.html_table.php @@ -0,0 +1,137 @@ + + * Name: html_table
+ * Date: Feb 17, 2003
+ * Purpose: make an html table from an array of data
+ * Input:
+ * - loop = array to loop through + * - cols = number of columns + * - rows = number of rows + * - table_attr = table attributes + * - tr_attr = table row attributes (arrays are cycled) + * - td_attr = table cell attributes (arrays are cycled) + * - trailpad = value to pad trailing cells with + * - vdir = vertical direction (default: "down", means top-to-bottom) + * - hdir = horizontal direction (default: "right", means left-to-right) + * - inner = inner loop (default "cols": print $loop line by line, + * $loop will be printed column by column otherwise) + * + * + * Examples: + *
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols=4 tr_attr=$colors}
+ * 
+ * @author Monte Ohrt + * @version 1.0 + * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_html_table($params, &$smarty) +{ + $table_attr = 'border="1"'; + $tr_attr = ''; + $td_attr = ''; + $cols = 3; + $rows = 3; + $trailpad = ' '; + $vdir = 'down'; + $hdir = 'right'; + $inner = 'cols'; + + if (!isset($params['loop'])) { + $smarty->trigger_error("html_table: missing 'loop' parameter"); + return; + } + + foreach ($params as $_key=>$_value) { + switch ($_key) { + case 'loop': + $$_key = (array)$_value; + break; + + case 'cols': + case 'rows': + $$_key = (int)$_value; + break; + + case 'table_attr': + case 'trailpad': + case 'hdir': + case 'vdir': + case 'inner': + $$_key = (string)$_value; + break; + + case 'tr_attr': + case 'td_attr': + $$_key = $_value; + break; + } + } + + $loop_count = count($loop); + if (empty($params['rows'])) { + /* no rows specified */ + $rows = ceil($loop_count/$cols); + } elseif (empty($params['cols'])) { + if (!empty($params['rows'])) { + /* no cols specified, but rows */ + $cols = ceil($loop_count/$rows); + } + } + + $output = "\n"; + + for ($r=0; $r<$rows; $r++) { + $output .= "\n"; + $rx = ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols; + + for ($c=0; $c<$cols; $c++) { + $x = ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c; + if ($inner!='cols') { + /* shuffle x to loop over rows*/ + $x = floor($x/$cols) + ($x%$cols)*$rows; + } + + if ($x<$loop_count) { + $output .= "" . $loop[$x] . "\n"; + } else { + $output .= "$trailpad\n"; + } + } + $output .= "\n"; + } + $output .= "
\n"; + + return $output; +} + +function smarty_function_html_table_cycle($name, $var, $no) { + if(!is_array($var)) { + $ret = $var; + } else { + $ret = $var[$no % count($var)]; + } + + return ($ret) ? ' '.$ret : ''; +} + + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.mailto.php b/include/smarty/plugins/function.mailto.php new file mode 100644 index 000000000..64c122ce4 --- /dev/null +++ b/include/smarty/plugins/function.mailto.php @@ -0,0 +1,163 @@ + + * Name: mailto
+ * Date: May 21, 2002 + * Purpose: automate mailto address link creation, and optionally + * encode them.
+ * Input:
+ * - address = e-mail address + * - text = (optional) text to display, default is address + * - encode = (optional) can be one of: + * * none : no encoding (default) + * * javascript : encode with javascript + * * javascript_charcode : encode with javascript charcode + * * hex : encode with hexidecimal (no javascript) + * - cc = (optional) address(es) to carbon copy + * - bcc = (optional) address(es) to blind carbon copy + * - subject = (optional) e-mail subject + * - newsgroups = (optional) newsgroup(s) to post to + * - followupto = (optional) address(es) to follow up to + * - extra = (optional) extra tags for the href link + * + * Examples: + *
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * 
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto} + * (Smarty online manual) + * @version 1.2 + * @author Monte Ohrt + * @author credits to Jason Sweat (added cc, bcc and subject functionality) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_mailto($params, &$smarty) +{ + $extra = ''; + + if (empty($params['address'])) { + $smarty->trigger_error("mailto: missing 'address' parameter"); + return; + } else { + $address = $params['address']; + } + + $text = $address; + + // netscape and mozilla do not decode %40 (@) in BCC field (bug?) + // so, don't encode it. + $mail_parms = array(); + foreach ($params as $var=>$value) { + switch ($var) { + case 'cc': + case 'bcc': + case 'followupto': + if (!empty($value)) + $mail_parms[] = $var.'='.str_replace('%40','@',rawurlencode($value)); + break; + + case 'subject': + case 'newsgroups': + $mail_parms[] = $var.'='.rawurlencode($value); + break; + + case 'extra': + case 'text': + $$var = $value; + + default: + } + } + + $mail_parm_vals = ''; + for ($i=0; $itrigger_error("mailto: 'encode' parameter must be none, javascript or hex"); + return; + } + + if ($encode == 'javascript' ) { + $string = 'document.write(\''.$text.'\');'; + + $js_encode = ''; + for ($x=0; $x < strlen($string); $x++) { + $js_encode .= '%' . bin2hex($string[$x]); + } + + return ''; + + } elseif ($encode == 'javascript_charcode' ) { + $string = ''.$text.''; + + for($x = 0, $y = strlen($string); $x < $y; $x++ ) { + $ord[] = ord($string[$x]); + } + + $_ret = "\n"; + + return $_ret; + + + } elseif ($encode == 'hex') { + + preg_match('!^(.*)(\?.*)$!',$address,$match); + if(!empty($match[2])) { + $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript."); + return; + } + $address_encode = ''; + for ($x=0; $x < strlen($address); $x++) { + if(preg_match('!\w!',$address[$x])) { + $address_encode .= '%' . bin2hex($address[$x]); + } else { + $address_encode .= $address[$x]; + } + } + $text_encode = ''; + for ($x=0; $x < strlen($text); $x++) { + $text_encode .= '&#x' . bin2hex($text[$x]).';'; + } + + $mailto = "mailto:"; + return ''.$text_encode.''; + + } else { + // no encoding + return ''.$text.''; + + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.math.php b/include/smarty/plugins/function.math.php new file mode 100644 index 000000000..043910770 --- /dev/null +++ b/include/smarty/plugins/function.math.php @@ -0,0 +1,83 @@ + + * Name: math
+ * Purpose: handle math computations in template
+ * @link http://smarty.php.net/manual/en/language.function.math.php {math} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_math($params, &$smarty) +{ + // be sure equation parameter is present + if (empty($params['equation'])) { + $smarty->trigger_error("math: missing equation parameter"); + return; + } + + $equation = $params['equation']; + + // make sure parenthesis are balanced + if (substr_count($equation,"(") != substr_count($equation,")")) { + $smarty->trigger_error("math: unbalanced parenthesis"); + return; + } + + // match all vars in equation, make sure all are passed + preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]+)!",$equation, $match); + $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10', + 'max','min','pi','pow','rand','round','sin','sqrt','srand','tan'); + + foreach($match[1] as $curr_var) { + if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) { + $smarty->trigger_error("math: function call $curr_var not allowed"); + return; + } + } + + foreach($params as $key => $val) { + if ($key != "equation" && $key != "format" && $key != "assign") { + // make sure value is not empty + if (strlen($val)==0) { + $smarty->trigger_error("math: parameter $key is empty"); + return; + } + if (!is_numeric($val)) { + $smarty->trigger_error("math: parameter $key: is not numeric"); + return; + } + $equation = preg_replace("/\b$key\b/",$val, $equation); + } + } + + eval("\$smarty_math_result = ".$equation.";"); + + if (empty($params['format'])) { + if (empty($params['assign'])) { + return $smarty_math_result; + } else { + $smarty->assign($params['assign'],$smarty_math_result); + } + } else { + if (empty($params['assign'])){ + printf($params['format'],$smarty_math_result); + } else { + $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result)); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.popup.php b/include/smarty/plugins/function.popup.php new file mode 100644 index 000000000..2ba54de5a --- /dev/null +++ b/include/smarty/plugins/function.popup.php @@ -0,0 +1,117 @@ + + * Name: popup
+ * Purpose: make text pop up in windows via overlib + * @link http://smarty.php.net/manual/en/language.function.popup.php {popup} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_popup($params, &$smarty) +{ + $append = ''; + foreach ($params as $_key=>$_value) { + switch ($_key) { + case 'text': + case 'trigger': + case 'function': + case 'inarray': + $$_key = (string)$_value; + if ($_key == 'function' || $_key == 'inarray') + $append .= ',' . strtoupper($_key) . ",'$_value'"; + break; + + case 'caption': + case 'closetext': + case 'status': + $append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'"; + break; + + case 'fgcolor': + case 'bgcolor': + case 'textcolor': + case 'capcolor': + case 'closecolor': + case 'textfont': + case 'captionfont': + case 'closefont': + case 'fgbackground': + case 'bgbackground': + case 'caparray': + case 'capicon': + case 'background': + case 'frame': + $append .= ',' . strtoupper($_key) . ",'$_value'"; + break; + + case 'textsize': + case 'captionsize': + case 'closesize': + case 'width': + case 'height': + case 'border': + case 'offsetx': + case 'offsety': + case 'snapx': + case 'snapy': + case 'fixx': + case 'fixy': + case 'padx': + case 'pady': + case 'timeout': + case 'delay': + $append .= ',' . strtoupper($_key) . ",$_value"; + break; + + case 'sticky': + case 'left': + case 'right': + case 'center': + case 'above': + case 'below': + case 'noclose': + case 'autostatus': + case 'autostatuscap': + case 'fullhtml': + case 'hauto': + case 'vauto': + case 'mouseoff': + case 'followmouse': + if ($_value) $append .= ',' . strtoupper($_key); + break; + + default: + $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING); + } + } + + if (empty($text) && !isset($inarray) && empty($function)) { + $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required"); + return false; + } + + if (empty($trigger)) { $trigger = "onmouseover"; } + + $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\''; + $retval .= $append . ');"'; + if ($trigger == 'onmouseover') + $retval .= ' onmouseout="nd();"'; + + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/function.popup_init.php b/include/smarty/plugins/function.popup_init.php new file mode 100644 index 000000000..f62c33c13 --- /dev/null +++ b/include/smarty/plugins/function.popup_init.php @@ -0,0 +1,39 @@ + + * Name: popup_init
+ * Purpose: initialize overlib + * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_popup_init($params, &$smarty) +{ + $zindex = 1000; + + if (!empty($params['zindex'])) { + $zindex = $params['zindex']; + } + + if (!empty($params['src'])) { + return '' . "\n" + . '' . "\n"; + } else { + $smarty->trigger_error("popup_init: missing src parameter"); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.capitalize.php b/include/smarty/plugins/modifier.capitalize.php new file mode 100644 index 000000000..2b9169cef --- /dev/null +++ b/include/smarty/plugins/modifier.capitalize.php @@ -0,0 +1,42 @@ + + * Name: capitalize
+ * Purpose: capitalize words in the string + * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE + * capitalize (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_capitalize($string, $uc_digits = false) +{ + smarty_modifier_capitalize_ucfirst(null, $uc_digits); + return preg_replace_callback('!\b\w+\b!', 'smarty_modifier_capitalize_ucfirst', $string); +} + +function smarty_modifier_capitalize_ucfirst($string, $uc_digits = null) +{ + static $_uc_digits = false; + + if(isset($uc_digits)) { + $_uc_digits = $uc_digits; + return; + } + + if(!preg_match('!\d!',$string[0]) || $_uc_digits) + return ucfirst($string[0]); + else + return $string[0]; +} + + +?> diff --git a/include/smarty/plugins/modifier.cat.php b/include/smarty/plugins/modifier.cat.php new file mode 100644 index 000000000..2e37940d4 --- /dev/null +++ b/include/smarty/plugins/modifier.cat.php @@ -0,0 +1,33 @@ + + * Name: cat
+ * Date: Feb 24, 2003 + * Purpose: catenate a value to a variable + * Input: string to catenate + * Example: {$var|cat:"foo"} + * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_cat($string, $cat) +{ + return $string . $cat; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.count_characters.php b/include/smarty/plugins/modifier.count_characters.php new file mode 100644 index 000000000..49ce655e8 --- /dev/null +++ b/include/smarty/plugins/modifier.count_characters.php @@ -0,0 +1,31 @@ + + * Name: count_characteres
+ * Purpose: count the number of characters in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php + * count_characters (Smarty online manual) + * @param string + * @param boolean include whitespace in the character count + * @return integer + */ +function smarty_modifier_count_characters($string, $include_spaces = false) +{ + if ($include_spaces) + return(strlen($string)); + + return preg_match_all("/[^\s]/",$string, $match); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.count_paragraphs.php b/include/smarty/plugins/modifier.count_paragraphs.php new file mode 100644 index 000000000..6a9833c97 --- /dev/null +++ b/include/smarty/plugins/modifier.count_paragraphs.php @@ -0,0 +1,28 @@ + + * Name: count_paragraphs
+ * Purpose: count the number of paragraphs in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * count_paragraphs (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_paragraphs($string) +{ + // count \r or \n characters + return count(preg_split('/[\r\n]+/', $string)); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.count_sentences.php b/include/smarty/plugins/modifier.count_sentences.php new file mode 100644 index 000000000..0c210f08f --- /dev/null +++ b/include/smarty/plugins/modifier.count_sentences.php @@ -0,0 +1,28 @@ + + * Name: count_sentences + * Purpose: count the number of sentences in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * count_sentences (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_sentences($string) +{ + // find periods with a word before but not after. + return preg_match_all('/[^\s]\.(?!\w)/', $string, $match); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.count_words.php b/include/smarty/plugins/modifier.count_words.php new file mode 100644 index 000000000..42c8a741c --- /dev/null +++ b/include/smarty/plugins/modifier.count_words.php @@ -0,0 +1,32 @@ + + * Name: count_words
+ * Purpose: count the number of words in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.words.php + * count_words (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_words($string) +{ + // split text by ' ',\r,\n,\f,\t + $split_array = preg_split('/\s+/',$string); + // count matches that contain alphanumerics + $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array); + + return count($word_count); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.date_format.php b/include/smarty/plugins/modifier.date_format.php new file mode 100644 index 000000000..2f36b3b79 --- /dev/null +++ b/include/smarty/plugins/modifier.date_format.php @@ -0,0 +1,48 @@ +_get_plugin_filepath('shared','make_timestamp'); +/** + * Smarty date_format modifier plugin + * + * Type: modifier
+ * Name: date_format
+ * Purpose: format datestamps via strftime
+ * Input:
+ * - string: input date string + * - format: strftime format for output + * - default_date: default date if $string is empty + * @link http://smarty.php.net/manual/en/language.modifier.date.format.php + * date_format (Smarty online manual) + * @param string + * @param string + * @param string + * @return string|void + * @uses smarty_make_timestamp() + */ +function smarty_modifier_date_format($string, $format="%b %e, %Y", $default_date=null) +{ + if (substr(PHP_OS,0,3) == 'WIN') { + $_win_from = array ('%e', '%T', '%D'); + $_win_to = array ('%#d', '%H:%M:%S', '%m/%d/%y'); + $format = str_replace($_win_from, $_win_to, $format); + } + if($string != '') { + return strftime($format, smarty_make_timestamp($string)); + } elseif (isset($default_date) && $default_date != '') { + return strftime($format, smarty_make_timestamp($default_date)); + } else { + return; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.debug_print_var.php b/include/smarty/plugins/modifier.debug_print_var.php new file mode 100644 index 000000000..b9bb18488 --- /dev/null +++ b/include/smarty/plugins/modifier.debug_print_var.php @@ -0,0 +1,56 @@ + + * Name: debug_print_var
+ * Purpose: formats variable contents for display in the console + * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php + * debug_print_var (Smarty online manual) + * @param array|object + * @param integer + * @param integer + * @return string + */ +function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40) +{ + $_replace = array("\n"=>'\n', "\r"=>'\r', "\t"=>'\t'); + if (is_array($var)) { + $results = "Array (".count($var).")"; + foreach ($var as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
".str_repeat(' ', $depth*2)."".strtr($curr_key, $_replace)." => $return"; + } + } else if (is_object($var)) { + $object_vars = get_object_vars($var); + $results = "".get_class($var)." Object (".count($object_vars).")"; + foreach ($object_vars as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
".str_repeat(' ', $depth*2)."$curr_key => $return"; + } + } else if (is_resource($var)) { + $results = ''.(string)$var.''; + } else if (empty($var) && $var != "0") { + $results = 'empty'; + } else { + if (strlen($var) > $length ) { + $results = substr($var, 0, $length-3).'...'; + } else { + $results = $var; + } + $results = htmlspecialchars($results); + $results = strtr($results, $_replace); + } + return $results; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.default.php b/include/smarty/plugins/modifier.default.php new file mode 100644 index 000000000..8268e396f --- /dev/null +++ b/include/smarty/plugins/modifier.default.php @@ -0,0 +1,31 @@ + + * Name: default
+ * Purpose: designate default value for empty variables + * @link http://smarty.php.net/manual/en/language.modifier.default.php + * default (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_default($string, $default = '') +{ + if (!isset($string) || $string === '') + return $default; + else + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.escape.php b/include/smarty/plugins/modifier.escape.php new file mode 100644 index 000000000..a32a8766c --- /dev/null +++ b/include/smarty/plugins/modifier.escape.php @@ -0,0 +1,89 @@ + + * Name: escape
+ * Purpose: Escape the string according to escapement type + * @link http://smarty.php.net/manual/en/language.modifier.escape.php + * escape (Smarty online manual) + * @param string + * @param html|htmlall|url|quotes|hex|hexentity|javascript + * @return string + */ +function smarty_modifier_escape($string, $esc_type = 'html') +{ + switch ($esc_type) { + case 'html': + return htmlspecialchars($string, ENT_QUOTES); + + case 'htmlall': + return htmlentities($string, ENT_QUOTES); + + case 'url': + return rawurlencode($string); + + case 'quotes': + // escape unescaped single quotes + return preg_replace("%(?'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n',''<\/')); + + case 'mail': + // safe way to display e-mail address on a web page + return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string); + + case 'nonstd': + // escape non-standard chars, such as ms document quotes + $_res = ''; + for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) { + $_ord = ord($string{$_i}); + // non-standard char, escape it + if($_ord >= 126){ + $_res .= '&#' . $_ord . ';'; + } + else { + $_res .= $string{$_i}; + } + } + return $_res; + + default: + return $string; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.indent.php b/include/smarty/plugins/modifier.indent.php new file mode 100644 index 000000000..1642bac3d --- /dev/null +++ b/include/smarty/plugins/modifier.indent.php @@ -0,0 +1,27 @@ + + * Name: indent
+ * Purpose: indent lines of text + * @link http://smarty.php.net/manual/en/language.modifier.indent.php + * indent (Smarty online manual) + * @param string + * @param integer + * @param string + * @return string + */ +function smarty_modifier_indent($string,$chars=4,$char=" ") +{ + return preg_replace('!^!m',str_repeat($char,$chars),$string); +} + +?> diff --git a/include/smarty/plugins/modifier.lower.php b/include/smarty/plugins/modifier.lower.php new file mode 100644 index 000000000..0b4d1517d --- /dev/null +++ b/include/smarty/plugins/modifier.lower.php @@ -0,0 +1,25 @@ + + * Name: lower
+ * Purpose: convert string to lowercase + * @link http://smarty.php.net/manual/en/language.modifier.lower.php + * lower (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_lower($string) +{ + return strtolower($string); +} + +?> diff --git a/include/smarty/plugins/modifier.nl2br.php b/include/smarty/plugins/modifier.nl2br.php new file mode 100644 index 000000000..d6fabff64 --- /dev/null +++ b/include/smarty/plugins/modifier.nl2br.php @@ -0,0 +1,35 @@ + + * Name: nl2br
+ * Date: Feb 26, 2003 + * Purpose: convert \r\n, \r or \n to <
> + * Input:
+ * - contents = contents to replace + * - preceed_test = if true, includes preceeding break tags + * in replacement + * Example: {$text|nl2br} + * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php + * nl2br (Smarty online manual) + * @version 1.0 + * @author Monte Ohrt + * @param string + * @return string + */ +function smarty_modifier_nl2br($string) +{ + return nl2br($string); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.regex_replace.php b/include/smarty/plugins/modifier.regex_replace.php new file mode 100644 index 000000000..7eee497c8 --- /dev/null +++ b/include/smarty/plugins/modifier.regex_replace.php @@ -0,0 +1,33 @@ + + * Name: regex_replace
+ * Purpose: regular epxression search/replace + * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php + * regex_replace (Smarty online manual) + * @param string + * @param string|array + * @param string|array + * @return string + */ +function smarty_modifier_regex_replace($string, $search, $replace) +{ + if (preg_match('!\W(\w+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) { + /* remove eval-modifier from $search */ + $search = substr($search, 0, -strlen($match[1])) . str_replace('e', '', $match[1]); + } + return preg_replace($search, $replace, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.replace.php b/include/smarty/plugins/modifier.replace.php new file mode 100644 index 000000000..2a43515f7 --- /dev/null +++ b/include/smarty/plugins/modifier.replace.php @@ -0,0 +1,29 @@ + + * Name: replace
+ * Purpose: simple search/replace + * @link http://smarty.php.net/manual/en/language.modifier.replace.php + * replace (Smarty online manual) + * @param string + * @param string + * @param string + * @return string + */ +function smarty_modifier_replace($string, $search, $replace) +{ + return str_replace($search, $replace, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.spacify.php b/include/smarty/plugins/modifier.spacify.php new file mode 100644 index 000000000..dad057f9b --- /dev/null +++ b/include/smarty/plugins/modifier.spacify.php @@ -0,0 +1,29 @@ + + * Name: spacify
+ * Purpose: add spaces between characters in a string + * @link http://smarty.php.net/manual/en/language.modifier.spacify.php + * spacify (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_spacify($string, $spacify_char = ' ') +{ + return implode($spacify_char, + preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY)); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.string_format.php b/include/smarty/plugins/modifier.string_format.php new file mode 100644 index 000000000..efd621506 --- /dev/null +++ b/include/smarty/plugins/modifier.string_format.php @@ -0,0 +1,28 @@ + + * Name: string_format
+ * Purpose: format strings via sprintf + * @link http://smarty.php.net/manual/en/language.modifier.string.format.php + * string_format (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_string_format($string, $format) +{ + return sprintf($format, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.strip.php b/include/smarty/plugins/modifier.strip.php new file mode 100644 index 000000000..cc5c453c8 --- /dev/null +++ b/include/smarty/plugins/modifier.strip.php @@ -0,0 +1,33 @@ + + * Name: strip
+ * Purpose: Replace all repeated spaces, newlines, tabs + * with a single space or supplied replacement string.
+ * Example: {$var|strip} {$var|strip:" "} + * Date: September 25th, 2002 + * @link http://smarty.php.net/manual/en/language.modifier.strip.php + * strip (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_strip($text, $replace = ' ') +{ + return preg_replace('!\s+!', $replace, $text); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.strip_tags.php b/include/smarty/plugins/modifier.strip_tags.php new file mode 100644 index 000000000..45f1ec14d --- /dev/null +++ b/include/smarty/plugins/modifier.strip_tags.php @@ -0,0 +1,31 @@ + + * Name: strip_tags
+ * Purpose: strip html tags from text + * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php + * strip_tags (Smarty online manual) + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_strip_tags($string, $replace_with_space = true) +{ + if ($replace_with_space) + return preg_replace('!<[^>]*?>!', ' ', $string); + else + return strip_tags($string); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.truncate.php b/include/smarty/plugins/modifier.truncate.php new file mode 100644 index 000000000..15a26ba97 --- /dev/null +++ b/include/smarty/plugins/modifier.truncate.php @@ -0,0 +1,43 @@ + + * Name: truncate
+ * Purpose: Truncate a string to a certain length if necessary, + * optionally splitting in the middle of a word, and + * appending the $etc string. + * @link http://smarty.php.net/manual/en/language.modifier.truncate.php + * truncate (Smarty online manual) + * @param string + * @param integer + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_truncate($string, $length = 80, $etc = '...', + $break_words = false) +{ + if ($length == 0) + return ''; + + if (strlen($string) > $length) { + $length -= strlen($etc); + if (!$break_words) + $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1)); + + return substr($string, 0, $length).$etc; + } else + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/modifier.upper.php b/include/smarty/plugins/modifier.upper.php new file mode 100644 index 000000000..69960ae72 --- /dev/null +++ b/include/smarty/plugins/modifier.upper.php @@ -0,0 +1,25 @@ + + * Name: upper
+ * Purpose: convert string to uppercase + * @link http://smarty.php.net/manual/en/language.modifier.upper.php + * upper (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_upper($string) +{ + return strtoupper($string); +} + +?> diff --git a/include/smarty/plugins/modifier.wordwrap.php b/include/smarty/plugins/modifier.wordwrap.php new file mode 100644 index 000000000..b9a9fe94b --- /dev/null +++ b/include/smarty/plugins/modifier.wordwrap.php @@ -0,0 +1,28 @@ + + * Name: wordwrap
+ * Purpose: wrap a string of text at a given length + * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php + * wordwrap (Smarty online manual) + * @param string + * @param integer + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false) +{ + return wordwrap($string,$length,$break,$cut); +} + +?> diff --git a/include/smarty/plugins/outputfilter.trimwhitespace.php b/include/smarty/plugins/outputfilter.trimwhitespace.php new file mode 100644 index 000000000..01e35e03d --- /dev/null +++ b/include/smarty/plugins/outputfilter.trimwhitespace.php @@ -0,0 +1,75 @@ + + * Type: outputfilter
+ * Name: trimwhitespace
+ * Date: Jan 25, 2003
+ * Purpose: trim leading white space and blank lines from + * template source after it gets interpreted, cleaning + * up code and saving bandwidth. Does not affect + * <
>
and blocks.
+ * Install: Drop into the plugin directory, call + * $smarty->load_filter('output','trimwhitespace'); + * from application. + * @author Monte Ohrt + * @author Contributions from Lars Noschinski + * @version 1.3 + * @param string + * @param Smarty + */ +function smarty_outputfilter_trimwhitespace($source, &$smarty) +{ + // Pull out the script blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_script_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SMARTY:TRIM:SCRIPT@@@', $source); + + // Pull out the pre blocks + preg_match_all("!
.*?
!is", $source, $match); + $_pre_blocks = $match[0]; + $source = preg_replace("!
.*?
!is", + '@@@SMARTY:TRIM:PRE@@@', $source); + + // Pull out the textarea blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_textarea_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SMARTY:TRIM:TEXTAREA@@@', $source); + + // remove all leading spaces, tabs and carriage returns NOT + // preceeded by a php close tag. + $source = trim(preg_replace('/((?)\n)[\s]+/m', '\1', $source)); + + // replace script blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source); + + // replace pre blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source); + + // replace textarea blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source); + + return $source; +} + +function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) { + $_len = strlen($search_str); + $_pos = 0; + for ($_i=0, $_count=count($replace); $_i<$_count; $_i++) + if (($_pos=strpos($subject, $search_str, $_pos))!==false) + $subject = substr_replace($subject, $replace[$_i], $_pos, $_len); + else + break; + +} + +?> diff --git a/include/smarty/plugins/shared.escape_special_chars.php b/include/smarty/plugins/shared.escape_special_chars.php new file mode 100644 index 000000000..515763abe --- /dev/null +++ b/include/smarty/plugins/shared.escape_special_chars.php @@ -0,0 +1,30 @@ + + * Purpose: used by other smarty functions to escape + * special chars except for already escaped ones + * @param string + * @return string + */ +function smarty_function_escape_special_chars($string) +{ + if(!is_array($string)) { + $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); + $string = htmlspecialchars($string); + $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string); + } + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/include/smarty/plugins/shared.make_timestamp.php b/include/smarty/plugins/shared.make_timestamp.php new file mode 100644 index 000000000..acdd77735 --- /dev/null +++ b/include/smarty/plugins/shared.make_timestamp.php @@ -0,0 +1,43 @@ + + * Purpose: used by other smarty functions to make a timestamp + * from a string. + * @param string + * @return string + */ +function smarty_make_timestamp($string) +{ + if(empty($string)) { + $string = "now"; + } + $time = strtotime($string); + if (is_numeric($time) && $time != -1) + return $time; + + // is mysql timestamp format of YYYYMMDDHHMMSS? + if (preg_match('/^\d{14}$/', $string)) { + $time = mktime(substr($string,8,2),substr($string,10,2),substr($string,12,2), + substr($string,4,2),substr($string,6,2),substr($string,0,4)); + + return $time; + } + + // couldn't recognize it, try to return a time + $time = (int) $string; + if ($time > 0) + return $time; + else + return time(); +} + +/* vim: set expandtab: */ + +?> diff --git a/include/version.inc b/include/version.inc new file mode 100644 index 000000000..b1efca856 --- /dev/null +++ b/include/version.inc @@ -0,0 +1,19 @@ +