From e2d6ed954b42c72645aeb2476591e6d42cf48991 Mon Sep 17 00:00:00 2001 From: tbrehm Date: Fri, 29 Jun 2007 14:32:16 +0000 Subject: [PATCH] - added basic update script - improved several functions in site module - added server classes to restart services --- install/install.php | 24 +- install/lib/installer_base.lib.php | 2 + install/sql/ispconfig3.sql | 2 + install/update.php | 155 ++ interface/lib/classes/tform.inc.php | 51 +- interface/lib/classes/tform_actions.inc.php | 39 +- interface/web/sites/form/ftp_user.tform.php | 13 +- .../web/sites/templates/ftp_user_advanced.htm | 4 +- interface/web/sites/web_domain_edit.php | 8 +- server/conf/vhost.conf.master | 39 +- server/lib/classes/file.inc.php | 319 ++++ server/lib/classes/services.inc.php | 79 + server/lib/classes/system.inc.php | 999 +++++++++++ server/lib/classes/tpl.inc.php | 1499 +++++++++++++++++ server/lib/classes/tpl_cache.inc.php | 186 ++ server/lib/classes/tpl_error.inc.php | 92 + server/lib/classes/tpl_ini.inc.php | 116 ++ server/mods-enabled/web_module.inc.php | 17 +- server/plugins-enabled/apache2_plugin.inc.php | 93 +- server/server.php | 11 +- 20 files changed, 3676 insertions(+), 72 deletions(-) create mode 100644 install/update.php create mode 100644 server/lib/classes/file.inc.php create mode 100644 server/lib/classes/services.inc.php create mode 100644 server/lib/classes/system.inc.php create mode 100644 server/lib/classes/tpl.inc.php create mode 100644 server/lib/classes/tpl_cache.inc.php create mode 100644 server/lib/classes/tpl_error.inc.php create mode 100644 server/lib/classes/tpl_ini.inc.php diff --git a/install/install.php b/install/install.php index 140db21a9..05fba1fd3 100644 --- a/install/install.php +++ b/install/install.php @@ -115,17 +115,19 @@ calmd spamd */ -exec("/etc/init.d/mysql restart"); -exec("/etc/init.d/postfix restart"); -exec("/etc/init.d/saslauthd restart"); -exec("/etc/init.d/amavis restart"); -exec("/etc/init.d/clamav-daemon restart"); -exec("/etc/init.d/courier-authdaemon restart"); -exec("/etc/init.d/courier-imap restart"); -exec("/etc/init.d/courier-imap-ssl restart"); -exec("/etc/init.d/courier-pop restart"); -exec("/etc/init.d/courier-pop-ssl restart"); -exec("/etc/init.d/apache2 restart"); +swriteln('Restarting services ...'); +system("/etc/init.d/mysql restart"); +system("/etc/init.d/postfix restart"); +system("/etc/init.d/saslauthd restart"); +system("/etc/init.d/amavis restart"); +system("/etc/init.d/clamav-daemon restart"); +system("/etc/init.d/courier-authdaemon restart"); +system("/etc/init.d/courier-imap restart"); +system("/etc/init.d/courier-imap-ssl restart"); +system("/etc/init.d/courier-pop restart"); +system("/etc/init.d/courier-pop-ssl restart"); +system("/etc/init.d/apache2 restart"); +system("/etc/init.d/pure-ftpd-mysql restart"); echo "Installation finished.\n"; diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 00f60cb9a..f97c4b442 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -467,6 +467,8 @@ maildrop unix - n n - - pipe wf($conf["dist_pureftpd_config_dir"].'/'.$configfile,$content); exec('chmod 600 '.$conf["dist_pureftpd_config_dir"].'/'.$configfile); exec('chown root:root '.$conf["dist_pureftpd_config_dir"].'/'.$configfile); + // enable chrooting + exec('echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone'); } diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql index c80510db3..1e552beee 100644 --- a/install/sql/ispconfig3.sql +++ b/install/sql/ispconfig3.sql @@ -404,6 +404,8 @@ CREATE TABLE `server` ( -- Daten für Tabelle `server` -- +INSERT INTO `server` (`server_id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_name`, `mail_server`, `web_server`, `dns_server`, `file_server`, `db_server`, `vserver_server`, `config`, `updated`, `active`) VALUES (1, 1, 1, 'riud', 'riud', 'r', 'Server 1', 1, 1, 1, 1, 1, 1, '[global]\nwebserver=apache\nmailserver=postfix\ndnsserver=mydns\n\n[mail]\nmodule=postfix_mysql\nmaildir_path=/home/vmail/[domain]/[localpart]/\nhomedir_path=/home/vmail/\nmailuser_uid=5000\nmailuser_gid=5000\nmailuser_name=vmail\nmailuser_group=vmail\n\n[getmail]\ngetmail_config_dir=/etc/getmail\n\n[web]\nwebsite_path=/var/clients/client[client_id]/web[website_id]\nwebsite_symlinks=/var/www/[website_domain]/:/var/clients/client[client_id]/[website_domain]/\n\n', 0, 1); + -- -------------------------------------------------------- -- diff --git a/install/update.php b/install/update.php new file mode 100644 index 000000000..0dc79198c --- /dev/null +++ b/install/update.php @@ -0,0 +1,155 @@ +request_language(); + +// TODO: all other queries, for testing I will setup everything in $conf + +// Initialize the MySQL server connection +include_once('lib/mysql.lib.php'); +$inst->db = new db(); + +// Database update is a bit brute force and should be rebuild later ;) + +// export the current database data +exec("mysqldump -h $conf[mysql_server_host] -u $conf[mysql_server_ispconfig_user] -p$conf[mysql_server_ispconfig_password] -c -t --add-drop-table --add-locks --all --quick --lock-tables $conf[mysql_server_database] > existing_db.sql &> /dev/null"); + +// Delete the old database +exec("/etc/init.d/mysql stop"); +exec("rm -rf /var/lib/mysql/".$conf["db_database"]); +exec("/etc/init.d/mysql start"); + +// Create the mysql database +$inst->configure_database(); + +// empty all databases +$db_tables = $inst->db->getTables(); +foreach($db_tables as $table) { + $inst->db->query("TRUNCATE $table"); +} + +// load old data back into database +exec("mysql -h $conf[mysql_server_host] -u $conf[mysql_server_ispconfig_user] -p$conf[mysql_server_ispconfig_password] $conf[mysql_server_database] < existing_db.sql &> /dev/null"); + +// Configure postfix +$inst->configure_postfix(); + +// Configure saslauthd +swriteln('Configuring SASL'); +$inst->configure_saslauthd(); + + +// Configure PAM +swriteln('Configuring PAM'); +$inst->configure_pam(); + +// Configure courier +swriteln('Configuring Courier'); +$inst->configure_courier(); + +// Configure Spamasassin +swriteln('Configuring Spamassassin'); +$inst->configure_spamassassin(); + +// Configure Amavis +swriteln('Configuring Amavisd'); +$inst->configure_amavis(); + +// Configure Getmail +swriteln('Configuring Getmail'); +$inst->configure_getmail(); + +// Configure Getmail +swriteln('Configuring Pureftpd'); +$inst->configure_pureftpd(); + +// Configure ISPConfig +swriteln('Installing ISPConfig'); +$inst->install_ispconfig(); + +// Configure ISPConfig +swriteln('Installing Crontab'); +$inst->install_crontab(); + + +/* +Restart services: +*/ + +swriteln('Restarting services ...'); +system("/etc/init.d/mysql restart"); +system("/etc/init.d/postfix restart"); +system("/etc/init.d/saslauthd restart"); +system("/etc/init.d/amavis restart"); +system("/etc/init.d/clamav-daemon restart"); +system("/etc/init.d/courier-authdaemon restart"); +system("/etc/init.d/courier-imap restart"); +system("/etc/init.d/courier-imap-ssl restart"); +system("/etc/init.d/courier-pop restart"); +system("/etc/init.d/courier-pop-ssl restart"); +system("/etc/init.d/apache2 restart"); +system("/etc/init.d/pure-ftpd-mysql restart"); + +echo "Update finished.\n"; + + +?> \ No newline at end of file diff --git a/interface/lib/classes/tform.inc.php b/interface/lib/classes/tform.inc.php index 81810b9cf..e631e2309 100644 --- a/interface/lib/classes/tform.inc.php +++ b/interface/lib/classes/tform.inc.php @@ -766,9 +766,7 @@ class tform { $app->error("Primary ID fehlt!"); } } - - // Daten in History tabelle speichern - if($this->errorMessage == '' and $this->formDef['db_history'] == 'yes') $this->datalogSave($action,$primary_id,$record); + return $sql; } @@ -839,11 +837,16 @@ class tform { // Set Wordbook for this form $app->tpl->setVar($this->wordbook); - } - + } + function getDataRecord($primary_id) { + global $app; + $sql = "SELECT * FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id; + return $app->db->queryOneRecord($sql); + } + - function datalogSave($action,$primary_id,$record_new) { + function datalogSave($action,$primary_id, $record_old, $record_new) { global $app,$conf; // Füge Backticks nur bei unvollständigen Tabellennamen ein @@ -852,17 +855,19 @@ class tform { } else { $escape = '`'; } - - if($action == "UPDATE") { + + /* + if($action == "UPDATE" or $action == "DELETE") { $sql = "SELECT * FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id; $record_old = $app->db->queryOneRecord($sql); } else { $record_old = array(); } + */ $diffrec = array(); - if(is_array($record_new)) { + if(is_array($record_new) && count($record_new) > 0) { foreach($record_new as $key => $val) { if($record_old[$key] != $val) { // Record has changed @@ -870,13 +875,22 @@ class tform { 'new' => $val); } } + } elseif(is_array($record_old)) { + foreach($record_old as $key => $val) { + if($record_new[$key] != $val) { + // Record has changed + $diffrec[$key] = array('new' => $record_new[$key], + 'old' => $val); + } + } } $this->diffrec = $diffrec; + // Full diff records for ISPConfig, they have a different format then the simple diffrec $diffrec_full = array(); - if(is_array($record_old)) { + if(is_array($record_old) && count($record_old) > 0) { foreach($record_old as $key => $val) { if(isset($record_new[$key]) && $record_new[$key] != $val) { // Record has changed @@ -887,6 +901,17 @@ class tform { $diffrec_full['new'][$key] = $val; } } + } elseif(is_array($record_new)) { + foreach($record_new as $key => $val) { + if(isset($record_new[$key]) && $record_old[$key] != $val) { + // Record has changed + $diffrec_full['new'][$key] = $val; + $diffrec_full['old'][$key] = $record_old[$key]; + } else { + $diffrec_full['new'][$key] = $val; + $diffrec_full['old'][$key] = $val; + } + } } /* @@ -903,7 +928,11 @@ class tform { $diffstr = $app->db->quote(serialize($diffrec_full)); $username = $app->db->quote($_SESSION["s"]["user"]["username"]); $dbidx = $this->formDef['db_table_idx'].":".$primary_id; - $action = ($action == 'INSERT')?'i':'u'; + // $action = ($action == 'INSERT')?'i':'u'; + + if($action == 'INSERT') $action = 'i'; + if($action == 'UPDATE') $action = 'u'; + if($action == 'DELETE') $action = 'd'; $sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$this->formDef['db_table']."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')"; $app->db->query($sql); } diff --git a/interface/lib/classes/tform_actions.inc.php b/interface/lib/classes/tform_actions.inc.php index f228e5414..89d974abd 100644 --- a/interface/lib/classes/tform_actions.inc.php +++ b/interface/lib/classes/tform_actions.inc.php @@ -102,9 +102,13 @@ class tform_actions { $ext_where = ''; $sql = $app->tform->getSQL($this->dataRecord,$app->tform->getCurrentTab(),'UPDATE',$this->id,$ext_where); if($app->tform->errorMessage == '') { + + if($app->tform->formDef['db_history'] == 'yes') { + $old_data_record = $app->tform->getDataRecord($this->id); + } if(!empty($sql)) { - $app->db->query($sql); + $app->db->query($sql); if($app->db->errorMessage != '') die($app->db->errorMessage); } @@ -118,6 +122,14 @@ class tform_actions { } $this->onAfterUpdate(); + + // Write data history (sys_datalog) + if($app->tform->formDef['db_history'] == 'yes') { + $new_data_record = $app->tform->getDataRecord($this->id); + $app->tform->datalogSave('UPDATE',$this->id,$old_data_record,$new_data_record); + unset($new_data_record); + unset($old_data_record); + } if($_REQUEST["next_tab"] == '') { $list_name = $_SESSION["s"]["form"]["return_to"]; @@ -176,6 +188,13 @@ class tform_actions { $this->onAfterInsert(); + // Write data history (sys_datalog) + if($app->tform->formDef['db_history'] == 'yes') { + $new_data_record = $app->tform->getDataRecord($this->id); + $app->tform->datalogSave('INSERT',$this->id,array(),$new_data_record); + unset($new_data_record); + } + if($_REQUEST["next_tab"] == '') { $list_name = $_SESSION["s"]["form"]["return_to"]; @@ -260,20 +279,10 @@ class tform_actions { $record_old = $app->db->queryOneRecord("SELECT * FROM ".$liste["table"]." WHERE ".$liste["table_idx"]." = ".$this->id); // Saving record to datalog when db_history enabled - if($form["db_history"] == 'yes') { - $diffrec = array(); - - foreach($record_old as $key => $val) { - // Record has changed - $diffrec[$key] = array('old' => $val, - 'new' => ''); - } - - $diffstr = $app->db->quote(serialize($diffrec)); - $username = $app->db->quote($_SESSION["s"]["user"]["username"]); - $dbidx = $app->tform->formDef['db_table_idx'].":".$this->id; - $sql = "INSERT INTO sys_datalog (dbtable,dbidx,action,tstamp,user,data) VALUES ('".$app->tform->formDef['db_table']."','$dbidx','d','".time()."','$username','$diffstr')"; - $app->db->query($sql); + if($app->tform->formDef["db_history"] == 'yes') { + $old_data_record = $app->tform->getDataRecord($this->id); + $app->tform->datalogSave('DELETE',$this->id,$old_data_record,array()); + unset($old_data_record); } $app->db->query("DELETE FROM ".$liste["table"]." WHERE ".$liste["table_idx"]." = ".$this->id); diff --git a/interface/web/sites/form/ftp_user.tform.php b/interface/web/sites/form/ftp_user.tform.php index 9c1399172..4950a1b2d 100644 --- a/interface/web/sites/form/ftp_user.tform.php +++ b/interface/web/sites/form/ftp_user.tform.php @@ -99,6 +99,7 @@ $form["tabs"]['ftp'] = array ( 'password' => array ( 'datatype' => 'VARCHAR', 'formtype' => 'PASSWORD', + 'encryption' => 'CRYPT', 'default' => '', 'value' => '', 'width' => '30', @@ -138,26 +139,26 @@ $form["tabs"]['advanced'] = array ( # Begin Datatable fields ################################## 'uid' => array ( - 'datatype' => 'INTEGER', + 'datatype' => 'VARCHAR', 'formtype' => 'TEXT', 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', 'errmsg'=> 'uid_error_empty'), ), 'default' => '0', 'value' => '', - 'width' => '5', - 'maxlength' => '5' + 'width' => '30', + 'maxlength' => '255' ), 'gid' => array ( - 'datatype' => 'INTEGER', + 'datatype' => 'VARCHAR', 'formtype' => 'TEXT', 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', 'errmsg'=> 'uid_error_empty'), ), 'default' => '0', 'value' => '', - 'width' => '5', - 'maxlength' => '5' + 'width' => '30', + 'maxlength' => '255' ), 'dir' => array ( 'datatype' => 'VARCHAR', diff --git a/interface/web/sites/templates/ftp_user_advanced.htm b/interface/web/sites/templates/ftp_user_advanced.htm index 97a09a468..b77b1e0e5 100644 --- a/interface/web/sites/templates/ftp_user_advanced.htm +++ b/interface/web/sites/templates/ftp_user_advanced.htm @@ -1,11 +1,11 @@ - + - + diff --git a/interface/web/sites/web_domain_edit.php b/interface/web/sites/web_domain_edit.php index e912002cc..5f208dbaf 100644 --- a/interface/web/sites/web_domain_edit.php +++ b/interface/web/sites/web_domain_edit.php @@ -167,7 +167,8 @@ class page_action extends tform_actions { // Get configuration for the web system $app->uses("getconf"); - $web_config = $app->getconf->get_server_config(intval($this->dataRecord["server_id"]),'web'); + $web_rec = $app->tform->getDataRecord($this->id); + $web_config = $app->getconf->get_server_config(intval($web_rec["server_id"]),'web'); $document_root = str_replace("[website_id]",$this->id,$web_config["website_path"]); // get the ID of the client @@ -202,7 +203,8 @@ class page_action extends tform_actions { // Get configuration for the web system $app->uses("getconf"); - $web_config = $app->getconf->get_server_config(intval($this->dataRecord["server_id"]),'web'); + $web_rec = $app->tform->getDataRecord($this->id); + $web_config = $app->getconf->get_server_config(intval($web_rec["server_id"]),'web'); $document_root = str_replace("[website_id]",$this->id,$web_config["website_path"]); // get the ID of the client @@ -211,7 +213,7 @@ class page_action extends tform_actions { $client = $app->db->queryOneRecord("SELECT client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); $client_id = intval($client["client_id"]); } else { - $client_id = intval($this->dataRecord["client_group_id"]); + $client_id = intval($web_rec["client_group_id"]); $client = $app->db->queryOneRecord("SELECT client_id FROM sys_group WHERE sys_group.groupid = ".intval($this->dataRecord["client_group_id"])); $client_id = intval($client["client_id"]); } diff --git a/server/conf/vhost.conf.master b/server/conf/vhost.conf.master index ca4aa3414..79ea7d724 100644 --- a/server/conf/vhost.conf.master +++ b/server/conf/vhost.conf.master @@ -1,25 +1,26 @@ -NameVirtualHost *:80 +# NameVirtualHost *:80 :80> DocumentRoot ServerName + ServerAlias - - - - - - - - - - - - - - - - - - + + # cgi enabled + + + # ssi enabled + + + # suexec enabled + + + # mod_php enabled + + + # suphp enabled + + + # php as cgi enabled + \ No newline at end of file diff --git a/server/lib/classes/file.inc.php b/server/lib/classes/file.inc.php new file mode 100644 index 000000000..e0bd12f6b --- /dev/null +++ b/server/lib/classes/file.inc.php @@ -0,0 +1,319 @@ +log("WARNING: could not open file ".$file, 2); + return false; + } else { + if(filesize($file) > 0){ + $content = fread($fp, filesize($file)); + } else { + $content = ""; + } + fclose($fp); + return $content; + } +} + +function wf($file, $content){ + global $app; + $this->mkdirs(dirname($file)); + if(!$fp = fopen ($file, "wb")){ + $app->log("WARNING: could not open file ".$file, 2); + return false; + } else { + fwrite($fp,$content); + fclose($fp); + return true; + } +} + +function af($file, $content){ + global $app; + $this->mkdirs(dirname($file)); + if(!$fp = fopen ($file, "ab")){ + $app->log("WARNING: could not open file ".$file, 2); + return false; + } else { + fwrite($fp,$content); + fclose($fp); + return true; + } +} + +function no_comments($file, $comment = '#'){ + $content = $this->unix_nl($this->rf($file)); + $lines = explode("\n", $content); + if(!empty($lines)){ + foreach($lines as $line){ + if(strstr($line, $comment)){ + $pos = strpos($line, $comment); + if($pos != 0){ + $new_lines[] = substr($line,0,$pos); + } else { + $new_lines[] = ""; + } + } else { + $new_lines[] = $line; + } + } + } + if(is_array($new_lines)){ + $content_without_comments = implode("\n", $new_lines); + $new_lines = NULL; + return $content_without_comments; + } else { + return ""; + } +} + +function manual_entries($file, $separator = '#### MAKE MANUAL ENTRIES BELOW THIS LINE! ####'){ + if(is_file($file)){ + $content = $this->rf($file); + $parts = explode($separator, $content); + $manual = "\n".trim($parts[1]); + return $manual; + } else { + return ""; + } +} + +function remove_blank_lines($input, $file = 1){ + //Leerzeilen löschen + if($file){ + $content = $this->unix_nl($this->rf($input)); + } else { + $content = $input; + } + $lines = explode("\n", $content); + if(!empty($lines)){ + foreach($lines as $line){ + if(trim($line) != "") $new_lines[] = $line; + } + } + if(is_array($new_lines)){ + $content = implode("\n", $new_lines); + } else { + $content = ""; + } + if($file){ + $this->wf($input, $content); + } else { + return $content; + } +} + +function unix_nl($input){ + $output = str_replace("\r\n", "\n", $input); + $output = str_replace("\r", "\n", $output); + return $output; +} + +function fileowner($file){ + $owner_id = fileowner($file); + clearstatcache(); + return $owner_id; +} + +function mkdirs($strPath, $mode = '0755'){ + // Verzeichnisse rekursiv erzeugen + if(is_dir($strPath)) return true; + $pStrPath = dirname($strPath); + if(!$this->mkdirs($pStrPath, $mode)) return false; + $old_umask = umask(0); + $ret_val = mkdir($strPath, octdec($mode)); + umask($old_umask); + return $ret_val; +} + +function find_includes($file){ + ob_start(); + $httpd_root = system('httpd -V | awk -F"\"" \'$1==" -D HTTPD_ROOT="{print $2}\''); + ob_end_clean(); + clearstatcache(); + if(is_file($file) && filesize($file) > 0){ + $includes[] = $file; + $inhalt = $this->unix_nl($this->no_comments($file)); + $lines = explode("\n", $inhalt); + if(!empty($lines)){ + foreach($lines as $line){ + if(stristr($line, "include ")){ + $include_file = str_replace("\n", "", trim(shell_exec("echo \"$line\" | awk '{print \$2}'"))); + if(substr($include_file,0,1) != "/"){ + $include_file = $httpd_root."/".$include_file; + } + if(is_file($include_file)){ + if($further_includes = $this->find_includes($include_file)){ + $includes = array_merge($includes, $further_includes); + } + } else { + if(strstr($include_file, "*")){ + $more_files = explode("\n", shell_exec("ls -l $include_file | awk '{print \$9}'")); + if(!empty($more_files)){ + foreach($more_files as $more_file){ + if(is_file($more_file)){ + if($further_includes = $this->find_includes($more_file)){ + $includes = array_merge($includes, $further_includes); + } + } + } + } + } + } + } + } + } + } + if(is_array($includes)){ + $includes = array_unique($includes); + return $includes; + } else { + return false; + } +} + +function edit_dist($var, $val){ + global $$var; + $files = array("/root/ispconfig/dist.inc.php"); + foreach($files as $file){ + if(is_file($file)){ + $file_content = $this->unix_nl($this->rf($file)); + $lines = explode("\n", $file_content); + for($i=0;$iwf($file, $file_content); + } + } +} + +function getDirectoryListing($dirname, $sortorder = "a", $show_subdirs = 0, $show_subdirfiles = 0, $exts = "", $ext_save = 1){ +// This function will return an array with filenames based on the criteria you can set in the variables +// @sortorder : a for ascending (the standard) or d for descending (you can use the "r" for reverse as well, works the same) +// @show_subdirs : 0 for NO, 1 for YES - meaning it will show the names of subdirectories if there are any +// Logically subdirnames will not be checked for the required extentions +// @show_subdirfiles : 0 for NO, 1 for YES - meaning it will show files from the subdirs +// Files from subdirs will be prefixed with the subdir name and checked for the required extentions. +// @exts can be either a string or an array, if not passed to the function, then the default will be a check for common image files +// If exts is set to "all" then all extentions are allowed +// @ext_save : 1 for YES, 0 for NO - meaning it will filter out system files or not (such as .htaccess) + + $dirname = realpath($dirname); + if (!$exts || empty($exts) || $exts == "") { + $exts = array("jpg", "gif", "jpeg", "png"); + } + if ($handle = opendir($dirname)) { + $filelist = array(); + while (false !== ($file = readdir($handle))) { + + // Filter out higher directory references + if ($file != "." && $file != "..") { + // Only look at directories or files, filter out symbolic links + if ( filetype ($dirname."/".$file) != "link") { + // If it's a file, check against valid extentions and add to the list + if ( filetype ($dirname."/".$file) == "file" ) { + if ($this->checkFileExtension($file, $exts, $ext_save)) { + $filelist[] = $file; + } + } + // If it's a directory and either subdirs should be listed or files from subdirs add relevant names to the list + else if ( filetype ($dirname."/".$file) == "dir" && ($show_subdirs == 1 || $show_subdirfiles == 1)) { + if ($show_subdirs == 1) { + $filelist[] = $file; + } + if ($show_subdirfiles == 1) { + $subdirname = $file; + $subdirfilelist = $this->getDirectoryListing($dirname."/".$subdirname."/", $sortorder, $show_subdirs, $show_subdirfiles, $exts, $ext_save); + for ($i = 0 ; $i < count($subdirfilelist) ; $i++) { + $subdirfilelist[$i] = $subdirname."/".$subdirfilelist[$i]; + } + $filelist = array_merge($filelist, $subdirfilelist); + } + + } + + } + } + } + closedir($handle); + + // Sort the results + if (count($filelist) > 1) { + natcasesort($filelist); + if ($sortorder == "d" || $sortorder == "r" ) { + $filelist = array_reverse($filelist, TRUE); + } + } + return $filelist; + } + else { + return false; + } +} + +function checkFileExtension($filename, $exts, $ext_save = 1){ + $passed = FALSE; + if ($ext_save == 1) { + if (preg_match("/^\./", $filename)) { + return $passed; + } + } + if ($exts == "all") { + $passed = TRUE; + return $passed; + } + if (is_string($exts)) { + if (eregi("\.". $exts ."$", $filename)) { + $passed = TRUE; + return $passed; + } + } else if (is_array($exts)) { + foreach ($exts as $theExt) { + if (eregi("\.". $theExt ."$", $filename)) { + $passed = TRUE; + return $passed; + } + } + } + return $passed; +} + +} +?> \ No newline at end of file diff --git a/server/lib/classes/services.inc.php b/server/lib/classes/services.inc.php new file mode 100644 index 000000000..260d3f0ed --- /dev/null +++ b/server/lib/classes/services.inc.php @@ -0,0 +1,79 @@ +registered_services[$service_name])) { + $this->delayed_restarts[$service_name] = $action; + } else { + $app->log("Unable to add a delayed restart for '$service_name'. Service '$service_name' is not registered.",LOGLEVEL_WARNING); + } + + } + + // This function restarts a service when the function is called + function restartService($service_name,$action = 'restart') { + global $app; + + if(is_array($this->registered_services[$service_name])) { + $module_name = $this->registered_services[$service_name]["module"]; + $function_name = $this->registered_services[$service_name]["function"]; + $app->log("Call function '$function_name' in module '$module_name'.",LOGLEVEL_DEBUG); + call_user_method($function_name,$app->loaded_modules[$module_name],$action); + } else { + $app->log("Unable to restart $service_name. Service $service_name is not registered.",LOGLEVEL_WARNING); + } + + } + + // This function is used to register callback functions for services that can be restarted + function registerService($service_name,$module_name, $function_name) { + global $app; + $this->registered_services[$service_name] = array('module' => $module_name, 'function' => $function_name); + $app->log("Registered Service '$service_name' in module '$module_name' for processing function '$function_name'",LOGLEVEL_DEBUG); + } + + // This function is called at the end of the server script to restart services. + function processDelayedActions() { + global $app; + foreach($this->delayed_restarts as $service_name => $action) { + $this->restartService($service_name,$action); + } + } + +} +?> \ No newline at end of file diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php new file mode 100644 index 000000000..977ed33cd --- /dev/null +++ b/server/lib/classes/system.inc.php @@ -0,0 +1,999 @@ +server_id = $go_info["isp"]["server_id"]; + $this->server_conf = $go_info["isp"]["server_conf"]; + $this->server_conf["passwd_datei"] = '/etc/passwd'; + $this->server_conf["shadow_datei"] = '/etc/shadow'; + $this->server_conf["group_datei"] = '/etc/group'; +} + +function hostname(){ + $dist = $this->server_conf["dist"]; + + ob_start(); + passthru("hostname"); + $hostname = ob_get_contents(); + ob_end_clean(); + $hostname = trim($hostname); + ob_start(); + if(!strstr($dist, "freebsd")){ + passthru("dnsdomainname"); + } else { + passthru("domainname"); + } + $domainname = ob_get_contents(); + ob_end_clean(); + $domainname = trim($domainname); + if($domainname != ""){ + if(!strstr($hostname, $domainname)) $hostname .= ".".$domainname; + } + return $hostname; +} + +function adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort = '*'){ + global $app; + if($this->is_user($user_username)){ + return false; + } else { + if(trim($user_username) != '') { + $user_datei = $this->server_conf["passwd_datei"]; + $shadow_datei = $this->server_conf["shadow_datei"]; + $shell = realpath($shell); + if(trim($passwort) == "") $passwort = '*'; + $new_user = "\n$user_username:x:$uid:$gid:$username:$homedir:$shell\n"; + $app->log->msg("USER: $new_user"); + $app->file->af($user_datei, $new_user); + if($shadow_datei == "/etc/shadow"){ + $datum = time(); + $tage = floor($datum/86400); + $new_passwd = "\n$user_username:$passwort:$tage:0:99999:7:::\n"; + } else { + $new_passwd = "\n$user_username:$passwort:$uid:$gid::0:0:$username:$homedir:$shell\n"; + } + $app->file->af($shadow_datei, $new_passwd); + + // TB: leere Zeilen entfernen + $app->file->remove_blank_lines($shadow_datei); + $app->file->remove_blank_lines($user_datei); + // TB: user Sortierung deaktiviert + //$this->order_users_groups(); + if($shadow_datei != "/etc/shadow"){ + $app->file->af($shadow_datei, "\n"); + + // TB: leere Zeilen entfernen + $app->file->remove_blank_lines($shadow_datei); + + $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__); + } + + return true; + } + } +} + +function updateuser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort = '*'){ + $this->deluser($user_username); + $this->adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort); +} + +function deactivateuser($user_username){ + $passwort = str_rot13($this->getpasswd($user_username)); + $user_attr = $this->get_user_attributes($user_username); + $uid = $user_attr["uid"]; + $gid = $user_attr["gid"]; + $username = $user_attr["name"]; + $homedir = $user_attr["homedir"]; + $shell = "/dev/null"; + $this->deluser($user_username); + $this->adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort); +} + +function deluser($user_username){ + global $app; + if($this->is_user($user_username)){ + $user_datei = $this->server_conf["passwd_datei"]; + $shadow_datei = $this->server_conf["shadow_datei"]; + $users = $app->file->rf($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + $num_lines = sizeof($lines); + for($i=0;$i<$num_lines;$i++){ + if(trim($lines[$i]) != ""){ + list($f1,) = explode(":", $lines[$i]); + if($f1 != $user_username) $new_lines[] = $lines[$i]; + } + } + $new_users = implode("\n", $new_lines); + $app->file->wf($user_datei, $new_users); + unset($new_lines); + unset($lines); + unset($new_users); + } + $app->file->remove_blank_lines($user_datei); + + $passwds = $app->file->rf($shadow_datei); + $lines = explode("\n", $passwds); + if(is_array($lines)){ + $num_lines = sizeof($lines); + for($i=0;$i<$num_lines;$i++){ + if(trim($lines[$i]) != ""){ + list($f1,) = explode(":", $lines[$i]); + if($f1 != $user_username) $new_lines[] = $lines[$i]; + } + } + $new_passwds = implode("\n", $new_lines); + $app->file->wf($shadow_datei, $new_passwds); + unset($new_lines); + unset($lines); + unset($new_passwds); + } + $app->file->remove_blank_lines($shadow_datei); + + $group_file = $app->file->rf($this->server_conf["group_datei"]); + $group_file_lines = explode("\n", $group_file); + foreach($group_file_lines as $group_file_line){ + if(trim($group_file_line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $group_file_line); + $group_users = explode(",", str_replace(" ", "", $f4)); + if(in_array($user_username, $group_users)){ + $g_users = array(); + foreach($group_users as $group_user){ + if($group_user != $user_username) $g_users[] = $group_user; + } + $f4 = implode(",", $g_users); + } + $new_group_file[] = $f1.":".$f2.":".$f3.":".$f4; + } + } + $new_group_file = implode("\n", $new_group_file); + $app->file->wf($this->server_conf["group_datei"], $new_group_file); + // TB: auskommentiert + //$this->order_users_groups(); + + if($shadow_datei != "/etc/shadow"){ + $app->file->af($shadow_datei, "\n"); + $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__); + } + return true; + } else { + return false; + } +} + +function addgroup($group, $gid, $members = ''){ + global $app; + if($this->is_group($group)){ + return false; + } else { + $group_datei = $this->server_conf["group_datei"]; + $shadow_datei = $this->server_conf["shadow_datei"]; + $new_group = "\n$group:x:$gid:$members\n"; + $app->file->af($group_datei, $new_group); + + // TB: auskommentiert + //$this->order_users_groups(); + if($shadow_datei != "/etc/shadow"){ + $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__); + } + return true; + } +} + +function updategroup($group, $gid, $members = ''){ + $this->delgroup($group); + $this->addgroup($group, $gid, $members); +} + +function delgroup($group){ + global $app; + if($this->is_group($group)){ + $group_datei = $this->server_conf["group_datei"]; + $shadow_datei = $this->server_conf["shadow_datei"]; + $groups = $app->file->rf($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + $num_lines = sizeof($lines); + for($i=0;$i<$num_lines;$i++){ + if(trim($lines[$i]) != ""){ + list($f1,) = explode(":", $lines[$i]); + if($f1 != $group) $new_lines[] = $lines[$i]; + } + } + $new_groups = implode("\n", $new_lines); + $app->file->wf($group_datei, $new_groups); + unset($new_lines); + unset($lines); + unset($new_groups); + } + // TB: auskommentiert + //$this->order_users_groups(); + if($shadow_datei != "/etc/shadow"){ + $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__); + } + return true; + } else { + return false; + } +} + +function order_users_groups(){ + global $app; + $user_datei = $this->server_conf["passwd_datei"]; + $shadow_datei = $this->server_conf["shadow_datei"]; + $group_datei = $this->server_conf["group_datei"]; + + $groups = $app->file->no_comments($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $line); + $arr[$f3] = $line; + } + } + } + ksort($arr); + reset($arr); + if($shadow_datei != "/etc/shadow"){ + $app->file->wf($group_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0)."\n"); + }else { + $app->file->wf($group_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0)); + } + unset($arr); + + $users = $app->file->no_comments($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3,) = explode(":", $line); + if($f1 != "toor"){ + $arr[$f3] = $line; + } else { + $arr[70000] = $line; + } + } + } + } + ksort($arr); + reset($arr); + $app->file->wf($user_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0)); + unset($arr); + + $passwds = $app->file->no_comments($shadow_datei); + $lines = explode("\n", $passwds); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3,) = explode(":", $line); + if($f1 != "toor"){ + $uid = $this->getuid($f1); + if(!is_bool($uid)) $arr[$uid] = $line; + } else { + $arr[70000] = $line; + } + } + } + } + ksort($arr); + reset($arr); + $app->file->wf($shadow_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0)); + unset($arr); +} + +function find_uid_gid($min, $max){ + global $app; + if($min < $max && $min >= 0 && $max >= 0 && $min <= 65536 && $max <= 65536 && is_int($min) && is_int($max)){ + for($i=$min;$i<=$max;$i++){ + $uid_arr[$i] = $gid_arr[$i] = 1; + } + $user_datei = $this->server_conf["passwd_datei"]; + $group_datei = $this->server_conf["group_datei"]; + + $users = $app->file->no_comments($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(":", $line); + if($f3 >= $min && $f3 <= $max) unset($uid_arr[$f3]); + } + } + if(!empty($uid_arr)){ + foreach($uid_arr as $key => $val){ + $uids[] = $key; + } + $min_uid = min($uids); + unset($uid_arr); + } else { + return false; + } + } + + $groups = $app->file->no_comments($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $line); + if($f3 >= $min && $f3 <= $max) unset($gid_arr[$f3]); + } + } + if(!empty($gid_arr)){ + foreach($gid_arr as $key => $val){ + $gids[] = $key; + } + $min_gid = min($gids); + unset($gid_arr); + } else { + return false; + } + } + + $result = array_intersect($uids, $gids); + $new_id = (max($result)); + unset($uids); + unset($gids); + unset($result); + if($new_id <= $max){ + return $new_id; + } else { + return false; + } + } else { + return false; + } +} + +function is_user($user){ + global $app; + $user_datei = $this->server_conf["passwd_datei"]; + $users = $app->file->no_comments($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(":", $line); + if($f1 == $user) return true; + } + } + } + return false; +} + +function is_group($group){ + global $app; + $group_datei = $this->server_conf["group_datei"]; + $groups = $app->file->no_comments($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $line); + if($f1 == $group) return true; + } + } + } + return false; +} + +function root_group(){ + global $app; + $group_datei = $this->server_conf["group_datei"]; + $groups = $app->file->no_comments($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $line); + if($f3 == 0) return $f1; + } + } + } + return false; +} + +function get_user_groups($username){ + global $app; + $user_groups = array(); + $group_datei = $this->server_conf["group_datei"]; + $groups = $app->file->no_comments($group_datei); + $lines = explode("\n", $groups); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $line); + if(intval($f3) < intval($this->server_conf["groupid_von"]) && trim($f1) != 'users'){ + $tmp_group_users = explode(',', str_replace(' ', '', $f4)); + if(in_array($username, $tmp_group_users) && trim($f1) != '') $user_groups[] = $f1; + unset($tmp_group_users); + } + } + } + } + if(!empty($user_groups)) return implode(',', $user_groups); + return ''; +} + +function getpasswd($user){ + global $app; + if($this->is_user($user)){ + $shadow_datei = $this->server_conf["shadow_datei"]; + $passwds = $app->file->no_comments($shadow_datei); + $lines = explode("\n", $passwds); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2,) = explode(":", $line); + if($f1 == $user) return $f2; + } + } + } + } else { + return false; + } +} + +function getuid($user){ + global $app; + if($this->is_user($user)){ + $user_datei = $this->server_conf["passwd_datei"]; + $users = $app->file->no_comments($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3,) = explode(":", $line); + if($f1 == $user) return $f3; + } + } + } + } else { + return false; + } +} + +function get_user_attributes($user){ + global $app; + if($this->is_user($user)){ + $user_datei = $this->server_conf["passwd_datei"]; + $users = $app->file->no_comments($user_datei); + $lines = explode("\n", $users); + if(is_array($lines)){ + foreach($lines as $line){ + if(trim($line) != ""){ + list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(":", $line); + if($f1 == $user){ + $user_attr["username"] = $f1; + $user_attr["x"] = $f2; + $user_attr["uid"] = $f3; + $user_attr["gid"] = $f4; + $user_attr["name"] = $f5; + $user_attr["homedir"] = $f6; + $user_attr["shell"] = $f7; + return $user_attr; + } + } + } + } + } else { + return false; + } +} + +function chown($file, $owner, $group = ''){ + $owner_change = @chown($file, $owner); + if($group != ""){ + $group_change = @chgrp($file, $group); + } else { + $group_change = 1; + } + if($owner_change && $group_change){ + return true; + } else { + return false; + } +} + +function add_user_to_group($group, $user = 'admispconfig'){ + global $app; + $group_file = $app->file->rf($this->server_conf["group_datei"]); + $group_file_lines = explode("\n", $group_file); + foreach($group_file_lines as $group_file_line){ + list($group_name,$group_x,$group_id,$group_users) = explode(":",$group_file_line); + if($group_name == $group){ + $group_users = explode(",", str_replace(" ", "", $group_users)); + if(!in_array($user, $group_users)){ + $group_users[] = $user; + } + $group_users = implode(",", $group_users); + if(substr($group_users,0,1) == ",") $group_users = substr($group_users,1); + $group_file_line = $group_name.":".$group_x.":".$group_id.":".$group_users; + } + $new_group_file[] = $group_file_line; + } + $new_group_file = implode("\n", $new_group_file); + $app->file->wf($this->server_conf["group_datei"], $new_group_file); + $app->file->remove_blank_lines($this->server_conf["group_datei"]); + if($this->server_conf["shadow_datei"] != "/etc/shadow"){ + $app->log->caselog("pwd_mkdb ".$this->server_conf["shadow_datei"]." &> /dev/null", $this->FILE, __LINE__); + } +} + +function usermod($user, $groups){ + global $app; + if($this->is_user($user)){ + $groups = explode(",", str_replace(" ", "", $groups)); + $group_file = $app->file->rf($this->server_conf["group_datei"]); + $group_file_lines = explode("\n", $group_file); + foreach($group_file_lines as $group_file_line){ + if(trim($group_file_line) != ""){ + list($f1, $f2, $f3, $f4) = explode(":", $group_file_line); + $group_users = explode(",", str_replace(" ", "", $f4)); + if(!in_array($f1, $groups)){ + if(in_array($user, $group_users)){ + $g_users = array(); + foreach($group_users as $group_user){ + if($group_user != $user) $g_users[] = $group_user; + } + $f4 = implode(",", $g_users); + } + } else { + if(!in_array($user, $group_users)){ + if(trim($group_users[0]) == "") unset($group_users); + $group_users[] = $user; + } + $f4 = implode(",", $group_users); + } + $new_group_file[] = $f1.":".$f2.":".$f3.":".$f4; + } + } + $new_group_file = implode("\n", $new_group_file); + $app->file->wf($this->server_conf["group_datei"], $new_group_file); + $app->file->remove_blank_lines($this->server_conf["group_datei"]); + if($this->server_conf["shadow_datei"] != "/etc/shadow"){ + $app->log->caselog("pwd_mkdb ".$this->server_conf["shadow_datei"]." &> /dev/null", $this->FILE, __LINE__); + } + return true; + } else { + return false; + } +} + +function rc_edit($service, $rl, $action){ + // $action = "on|off"; + global $app; + $dist_init_scripts = $app->system->server_conf["dist_init_scripts"]; + $dist_runlevel = $app->system->server_conf["dist_runlevel"]; + $dist = $app->system->server_conf["dist"]; + if(trim($dist_runlevel) == ""){ // falls es keine runlevel gibt (FreeBSD) + if($action == "on"){ + @symlink($dist_init_scripts."/".$service, $dist_init_scripts."/".$service.".sh"); + } + if($action == "off"){ + if(is_link($dist_init_scripts."/".$service.".sh")){ + unlink($dist_init_scripts."/".$service.".sh"); + } else { + exec("mv -f ".$dist_init_scripts."/".$service.".sh ".$dist_init_scripts."/".$service." &> /dev/null"); + } + } + } else { // Linux + if(substr($dist, 0,4) == 'suse'){ + if($action == "on"){ + exec("chkconfig --add $service &> /dev/null"); + } + if($action == "off"){ + exec("chkconfig --del $service &> /dev/null"); + } + } else { + $runlevels = explode(",", $rl); + foreach($runlevels as $runlevel){ + $runlevel = trim($runlevel); + if($runlevel != "" && is_dir($dist_runlevel."/rc".$runlevel.".d")){ + $handle=opendir($dist_runlevel."/rc".$runlevel.".d"); + while($file = readdir($handle)){ + if($file != "." && $file != ".."){ + $target = @readlink($dist_runlevel."/rc".$runlevel.".d/".$file); + if(strstr($file, $service) && strstr($target, $service) && substr($file,0,1) == "S") $ln_arr[$runlevel][] = $dist_runlevel."/rc".$runlevel.".d/".$file; + } + } + closedir($handle); + } + if($action == "on"){ + if(!is_array($ln_arr[$runlevel])) @symlink($dist_init_scripts."/".$service, $dist_runlevel."/rc".$runlevel.".d/S99".$service); + } + if($action == "off"){ + if(is_array($ln_arr[$runlevel])){ + foreach($ln_arr[$runlevel] as $link){ + unlink($link); + } + } + } + } + } + } +} + +function grep($content, $string, $params = ''){ + global $app; + // params: i, v, w + $content = $app->file->unix_nl($content); + $lines = explode("\n", $content); + foreach($lines as $line){ + if(!strstr($params, 'w')){ + if(strstr($params, 'i')){ + if(strstr($params, 'v')){ + if(!stristr($line, $string)) $find[] = $line; + } else { + if(stristr($line, $string)) $find[] = $line; + } + } else { + if(strstr($params, 'v')){ + if(!strstr($line, $string)) $find[] = $line; + } else { + if(strstr($line, $string)) $find[] = $line; + } + } + } else { + if(strstr($params, 'i')){ + if(strstr($params, 'v')){ + if(!$app->string->is_word($string, $line, 'i')) $find[] = $line; + } else { + if($app->string->is_word($string, $line, 'i')) $find[] = $line; + } + } else { + if(strstr($params, 'v')){ + if(!$app->string->is_word($string, $line)) $find[] = $line; + } else { + if($app->string->is_word($string, $line)) $find[] = $line; + } + } + } + } + if(is_array($find)){ + $ret_val = implode("\n", $find); + if(substr($ret_val,-1) != "\n") $ret_val .= "\n"; + $find = NULL; + return $ret_val; + } else { + return false; + } +} + +function cut($content, $field, $delimiter = ':'){ + global $app; + $content = $app->file->unix_nl($content); + $lines = explode("\n", $content); + foreach($lines as $line){ + $elms = explode($delimiter, $line); + $find[] = $elms[($field-1)]; + } + if(is_array($find)){ + $ret_val = implode("\n", $find); + if(substr($ret_val,-1) != "\n") $ret_val .= "\n"; + $find = NULL; + return $ret_val; + } else { + return false; + } +} + +function cat($file){ + global $app; + return $app->file->rf($file); +} + +function daemon_init($daemon, $action){ + // $action = start|stop|restart|reload + global $app; + $dist = $this->server_conf["dist"]; + $dist_init_scripts = $this->server_conf["dist_init_scripts"]; + if(!strstr($dist, "freebsd")){ + $app->log->caselog("$dist_init_scripts/$daemon $action &> /dev/null", $this->FILE, __LINE__); + } else { + if(is_file($dist_init_scripts."/".$daemon.".sh") || is_link($dist_init_scripts."/".$daemon.".sh")){ + if($action == "start" || $action == "stop"){ + $app->log->caselog($dist_init_scripts."/".$daemon.".sh ".$action." &> /dev/null", $this->FILE, __LINE__); + } else { + $app->log->caselog($dist_init_scripts."/".$daemon.".sh stop &> /dev/null", $this->FILE, __LINE__); + sleep(3); + $app->log->caselog($dist_init_scripts."/".$daemon.".sh start &> /dev/null", $this->FILE, __LINE__); + } + } else { + if(is_file($dist_init_scripts."/".$daemon) || is_link($dist_init_scripts."/".$daemon)){ + if($action == "start" || $action == "stop"){ + $app->log->caselog($dist_init_scripts."/".$daemon." ".$action." &> /dev/null", $this->FILE, __LINE__); + } else { + $app->log->caselog($dist_init_scripts."/".$daemon." stop &> /dev/null", $this->FILE, __LINE__); + sleep(3); + $app->log->caselog($dist_init_scripts."/".$daemon." start &> /dev/null", $this->FILE, __LINE__); + } + } else { + if(is_file("/etc/rc.d/".$daemon) || is_link("/etc/rc.d/".$daemon)){ + if($action == "start" || $action == "stop"){ + $app->log->caselog("/etc/rc.d/".$daemon." ".$action." &> /dev/null", $this->FILE, __LINE__); + } else { + $app->log->caselog("/etc/rc.d/".$daemon." stop &> /dev/null", $this->FILE, __LINE__); + sleep(3); + $app->log->caselog("/etc/rc.d/".$daemon." start &> /dev/null", $this->FILE, __LINE__); + } + } + } + } + } +} + +function netmask($netmask){ + list($f1,$f2,$f3,$f4) = explode(".", trim($netmask)); + $bin = str_pad(decbin($f1),8,"0",STR_PAD_LEFT).str_pad(decbin($f2),8,"0",STR_PAD_LEFT).str_pad(decbin($f3),8,"0",STR_PAD_LEFT).str_pad(decbin($f4),8,"0",STR_PAD_LEFT); + $parts = explode("0", $bin); + $bin = str_pad($parts[0], 32, "0", STR_PAD_RIGHT); + $bin = wordwrap($bin, 8, ".", 1); + list($f1,$f2,$f3,$f4) = explode(".", trim($bin)); + return bindec($f1).".".bindec($f2).".".bindec($f3).".".bindec($f4); +} + +function binary_netmask($netmask){ + list($f1,$f2,$f3,$f4) = explode(".", trim($netmask)); + $bin = str_pad(decbin($f1),8,"0",STR_PAD_LEFT).str_pad(decbin($f2),8,"0",STR_PAD_LEFT).str_pad(decbin($f3),8,"0",STR_PAD_LEFT).str_pad(decbin($f4),8,"0",STR_PAD_LEFT); + $parts = explode("0", $bin); + return substr_count($parts[0], "1"); +} + +function network($ip, $netmask){ + $netmask = $this->netmask($netmask); + list($f1,$f2,$f3,$f4) = explode(".", $netmask); + $netmask_bin = str_pad(decbin($f1),8,"0",STR_PAD_LEFT).str_pad(decbin($f2),8,"0",STR_PAD_LEFT).str_pad(decbin($f3),8,"0",STR_PAD_LEFT).str_pad(decbin($f4),8,"0",STR_PAD_LEFT); + list($f1,$f2,$f3,$f4) = explode(".", $ip); + $ip_bin = str_pad(decbin($f1),8,"0",STR_PAD_LEFT).str_pad(decbin($f2),8,"0",STR_PAD_LEFT).str_pad(decbin($f3),8,"0",STR_PAD_LEFT).str_pad(decbin($f4),8,"0",STR_PAD_LEFT); + for($i=0;$i<32;$i++){ + $network_bin .= substr($netmask_bin,$i,1) * substr($ip_bin,$i,1); + } + $network_bin = wordwrap($network_bin, 8, ".", 1); + list($f1,$f2,$f3,$f4) = explode(".", trim($network_bin)); + return bindec($f1).".".bindec($f2).".".bindec($f3).".".bindec($f4); +} + +function broadcast($ip, $netmask){ + $netmask = $this->netmask($netmask); + $binary_netmask = $this->binary_netmask($netmask); + list($f1,$f2,$f3,$f4) = explode(".", $ip); + $ip_bin = str_pad(decbin($f1),8,"0",STR_PAD_LEFT).str_pad(decbin($f2),8,"0",STR_PAD_LEFT).str_pad(decbin($f3),8,"0",STR_PAD_LEFT).str_pad(decbin($f4),8,"0",STR_PAD_LEFT); + $broadcast_bin = str_pad(substr($ip_bin, 0, $binary_netmask),32,"1",STR_PAD_RIGHT); + $broadcast_bin = wordwrap($broadcast_bin, 8, ".", 1); + list($f1,$f2,$f3,$f4) = explode(".", trim($broadcast_bin)); + return bindec($f1).".".bindec($f2).".".bindec($f3).".".bindec($f4); +} + +function network_info(){ + $dist = $this->server_conf["dist"]; + ob_start(); + passthru("ifconfig"); + $output = ob_get_contents(); + ob_end_clean(); + $lines = explode("\n", $output); + foreach($lines as $line){ + $elms = explode(" ", $line); + if(trim($elms[0]) != "" && substr($elms[0],0,1) != "\t"){ + $elms[0] = trim($elms[0]); + if(strstr($dist, "freebsd")) $elms[0] = substr($elms[0],0,-1); + $interfaces[] = $elms[0]; + } + } + if(!empty($interfaces)){ + foreach($interfaces as $interface){ + ob_start(); + if(!strstr($dist, "freebsd")){ + passthru("ifconfig ".$interface." | grep -iw 'inet' | cut -f2 -d: | cut -f1 -d' '"); + }else { + passthru("ifconfig ".$interface." | grep -iw 'inet' | grep -iv 'inet6' | cut -f2 -d' '"); + } + $output = trim(ob_get_contents()); + ob_end_clean(); + if($output != ""){ + $ifconfig["INTERFACE"][$interface] = $output; + $ifconfig["IP"][$output] = $interface; + } + } + if(!empty($ifconfig)){ + return $ifconfig; + } else { + return false; + } + } else { + return false; + } +} + +function network_config(){ + $ifconfig = $this->network_info(); + if($ifconfig){ + $main_interface = $ifconfig["IP"][$this->server_conf["server_ip"]]; + if(strstr($main_interface, ":")){ + $parts = explode(":", $main_interface); + $main_interface = trim($parts[0]); + } + if($main_interface != ""){ + $ips = $this->data["isp_server_ip"]; + if(!empty($ips)){ + foreach($ips as $ip){ + if(!isset($ifconfig["IP"][$ip["server_ip"]])){ + $to_set[] = $ip["server_ip"]; + } else { + unset($ifconfig["IP"][$ip["server_ip"]]); + } + } + if(!empty($ifconfig["IP"])){ + foreach($ifconfig["IP"] as $key => $val){ + if(!strstr($val, "lo") && !strstr($val, "lp") && strstr($val, $main_interface)){ + exec("ifconfig ".$val." down &> /dev/null"); + unset($ifconfig["INTERFACE"][$val]); + } + } + } + if(!empty($to_set)){ + foreach($to_set as $to){ + $i = 0; + while($i >= 0){ + if(isset($ifconfig["INTERFACE"][$main_interface.":".$i])){ + $i++; + } else { + $new_interface = $main_interface.":".$i; + $i = -1; + } + } + exec("ifconfig ".$new_interface." ".$to." netmask ".$this->server_conf["server_netzmaske"]." up &> /dev/null"); + $ifconfig["INTERFACE"][$new_interface] = $to; + } + } + } + } + } +} + +function quota_dirs(){ + global $app; + $content = $app->file->unix_nl($app->file->no_comments("/etc/fstab")); + $lines = explode("\n", $content); + foreach($lines as $line){ + $line = trim($line); + if($line != ""){ + $elms = explode("\t", $line); + foreach($elms as $elm){ + if(trim($elm) != "") $f[] = $elm; + } + if(!empty($f) && stristr($f[3], "userquota") && stristr($f[3], "groupquota")){ + $q_dirs[] = trim($f[1]); + } + unset($f); + } + } + if(!empty($q_dirs)){ + return $q_dirs; + } else { + return false; + } +} + +function make_trashscan(){ + global $app; + //trashscan erstellen + // Template Öffnen + $app->tpl->clear_all(); + $app->tpl->define( array(table => "trashscan.master")); + + if(!isset($this->server_conf["virusadmin"]) || trim($this->server_conf["virusadmin"]) == "") $this->server_conf["virusadmin"] = "admispconfig@localhost"; + if(substr($this->server_conf["virusadmin"],0,1) == "#"){ + $notify = "no"; + } else { + $notify = "yes"; + } + + // Variablen zuweisen + $app->tpl->assign( array(VIRUSADMIN => $this->server_conf["virusadmin"], + NOTIFICATION => $notify)); + + $app->tpl->parse(TABLE, table); + + $trashscan_text = $app->tpl->fetch(); + + $datei = "/home/admispconfig/ispconfig/tools/clamav/bin/trashscan"; + $app->file->wf($datei, $trashscan_text); + + exec("chown admispconfig:admispconfig $datei &> /dev/null"); + exec("chmod 755 $datei"); +} + +function get_time(){ + $addr = "http://www.ispconfig.org/"; + $timeout = 1; + $url_parts = parse_url($addr); + $path = $url_parts["path"]; + $port = 80; + $urlHandle = @fsockopen($url_parts["host"], $port, $errno, $errstr, $timeout); + if ($urlHandle){ + socket_set_timeout($urlHandle, $timeout); + + $urlString = "GET $path HTTP/1.0\r\nHost: ".$url_parts["host"]."\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"; + if ($user) $urlString .= "Authorization: Basic ".base64_encode("$user:$pass")."\r\n"; + $urlString .= "\r\n"; + fputs($urlHandle, $urlString); + + $month["Jan"] = "01"; + $month["Feb"] = "02"; + $month["Mar"] = "03"; + $month["Apr"] = "04"; + $month["May"] = "05"; + $month["Jun"] = "06"; + $month["Jul"] = "07"; + $month["Aug"] = "08"; + $month["Sep"] = "09"; + $month["Oct"] = "10"; + $month["Nov"] = "11"; + $month["Dec"] = "12"; + $c = 0; + $l = 0; + $startzeit = time(); + while(!feof($urlHandle) && $c < 2 && $l == 0){ + $line = trim(fgets($urlHandle,128)); + $response .= $line; + $c = time() - $startzeit; + if($line == "" || substr($line, 0, 5) == "Date:") $l += 1; // nur den Header auslesen + if(substr($line, 0, 5) == "Date:"){ + $parts = explode(" ", $line); + $tag = $parts[2]; + $monat = $month[$parts[3]]; + $jahr = $parts[4]; + list($stunde, $minute, $sekunde) = explode(":", $parts[5]); + $timestamp = mktime($stunde,$minute,$sekunde,$monat,$tag,$jahr); + } + } + + @fclose($urlHandle); + + return $timestamp; + } else { + @fclose($urlHandle); + return false; + } +} + +} +?> \ No newline at end of file diff --git a/server/lib/classes/tpl.inc.php b/server/lib/classes/tpl.inc.php new file mode 100644 index 000000000..e16f0dcb1 --- /dev/null +++ b/server/lib/classes/tpl.inc.php @@ -0,0 +1,1499 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: class.tpl.inc.php,v 1.1 2003/07/08 12:31:10 platinum Exp $ + +// check to avoid multiple including of class +if (!defined('vlibTemplateClassLoaded')) { + define('vlibTemplateClassLoaded', 1); + + include_once ($conf['classpath'].'/tpl_error.inc.php'); + include_once ($conf['classpath'].'/tpl_ini.inc.php'); + + /** + * vlibTemplate is a class used to seperate PHP and HTML. + * For instructions on how to use vlibTemplate, see the + * vlibTemplate.html file, located in the 'docs' directory. + * + * @since 07/03/2002 + * @author Kelvin Jones + * @package vLIB + * @access public + * @see vlibTemplate.html + */ + + class tpl { + + /*-----------------------------------------------------------------------------\ + | ATTENTION | + | Do not touch the following variables. vlibTemplate will not work otherwise. | + \-----------------------------------------------------------------------------*/ + + var $OPTIONS = array( + 'MAX_INCLUDES' => 10, + 'TEMPLATE_DIR' => null, + 'GLOBAL_VARS' => null, + 'GLOBAL_CONTEXT_VARS' => null, + 'LOOP_CONTEXT_VARS' => null, + 'SET_LOOP_VAR' => null, + 'DEFAULT_ESCAPE' => null, + 'STRICT' => null, + 'CASELESS' => null, + 'UNKNOWNS' => null, + 'TIME_PARSE' => null, + 'ENABLE_PHPINCLUDE' => null, + 'INCLUDE_PATHS' => array(), + 'CACHE_DIRECTORY' => null, + 'CACHE_LIFETIME' => null, + 'CACHE_EXTENSION' => null + ); + + /** open and close tags used for escaping */ + var $ESCAPE_TAGS = array( + 'html' => array('open' => 'htmlspecialchars(' + ,'close'=> ', ENT_QUOTES)'), + 'url' => array('open' => 'urlencode(' + ,'close'=> ')'), + 'rawurl'=>array('open' => 'rawurlencode(' + ,'close'=> ')'), + 'sq' => array('open' => 'addcslashes(' + ,'close'=> ", \"'\")"), + 'dq' => array('open' => 'addcslashes(' + ,'close'=> ", '\"')"), + '1' => array('open' => 'htmlspecialchars(' + ,'close'=> ', ENT_QUOTES)'), + '0' => array('open' => '' + ,'close'=> ''), + 'none' => array('open' => '' + ,'close'=> ''), + 'hex' => array('open' => '$this->_escape_hex(', + 'close'=> ', false)'), + 'hexentity' => array('open' => '$this->_escape_hex(', + 'close'=> ', true)') + ); + + /** open and close tags used for formatting */ + var $FORMAT_TAGS = array( + 'strtoupper' => array('open' => 'strtoupper(', + 'close'=> ')'), + 'uc' => array('open' => 'strtoupper(', + 'close'=> ')'), + 'strtolower' => array('open' => 'strtolower(', + 'close'=> ')'), + 'lc' => array('open' => 'strtolower(', + 'close'=> ')'), + 'ucfirst' => array('open' => 'ucfirst(', + 'close'=> ')'), + 'lcucfirst' => array('open' => 'ucfirst(strtolower(', + 'close'=> '))'), + 'ucwords' => array('open' => 'ucwords(', + 'close'=> ')'), + 'lcucwords' => array('open' => 'ucwords(strtolower(', + 'close'=> '))') + ); + + /** operators allowed when using extended TMPL_IF syntax */ + var $allowed_if_ops = array('==','!=','<>','<','>','<=','>='); + + /** dbs allowed by vlibTemplate::setDbLoop(). */ + var $allowed_loop_dbs = array('MYSQL','POSTGRESQL','INFORMIX','INTERBASE','INGRES', + 'MSSQL','MSQL','OCI8','ORACLE','OVRIMOS','SYBASE'); + + /** root directory of vlibTemplate automagically filled in */ + var $VLIBTEMPLATE_ROOT = null; + + /** contains current directory used when doing recursive include */ + var $_currentincludedir = array(); + + /** current depth of includes */ + var $_includedepth = 0; + + /** full path to tmpl file */ + var $_tmplfilename = null; + + /** file data before it's parsed */ + var $_tmplfile = null; + + /** parsed version of file, ready for eval()ing */ + var $_tmplfilep = null; + + /** eval()ed version ready for printing or whatever */ + var $_tmploutput = null; + + /** array for variables to be kept */ + var $_vars = array(); + + /** array where loop variables are kept */ + var $_arrvars = array(); + + /** array which holds the current namespace during parse */ + var $_namespace = array(); + + /** variable is set to true once the template is parsed, to save re-parsing everything */ + var $_parsed = false; + + /** array holds all unknowns vars */ + var $_unknowns = array(); + + /** microtime when template parsing began */ + var $_firstparsetime = null; + + /** total time taken to parse template */ + var $_totalparsetime = null; + + /** name of current loop being passed in */ + var $_currloopname = null; + + /** rows with the above loop */ + var $_currloop = array(); + + /** define vars to avoid warnings */ + var $_debug = null; + var $_cache = null; + + /** array which holds the dynamic Includes */ + var $_dyninclude = array(); + /*-----------------------------------------------------------------------------\ + | public functions | + \-----------------------------------------------------------------------------*/ + + + /** + * FUNCTION: newTemplate + * + * Usually called by the class constructor. + * Stores the filename in $this->_tmplfilename. + * Raises an error if the template file is not found. + * + * @param string $tmplfile full path to template file + * @return boolean true + * @access public + */ + function newTemplate ($tmplfile) { + if (!$tfile = $this->_fileSearch($tmplfile)) vlibTemplateError::raiseError('VT_ERROR_NOFILE',KILL,$tmplfile); + + // make sure that any parsing vars are cleared for the new template + $this->_tmplfile = null; + $this->_tmplfilep = null; + $this->_tmploutput = null; + $this->_parsed = false; + $this->_unknowns = array(); + $this->_firstparsetime = null; + $this->_totalparsetime = null; + + // reset debug module + if ($this->_debug) $this->_debugReset(); + + $this->_tmplfilename = $tfile; + return true; + } + + /** + * FUNCTION: setVar + * + * Sets variables to be used by the template + * If $k is an array, then it will treat it as an associative array + * using the keys as variable names and the values as variable values. + * + * @param mixed $k key to define variable name + * @param mixed $v variable to assign to $k + * @return boolean true/false + * @access public + */ + function setVar ($k,$v=null) { + if (is_array($k)) { + foreach($k as $key => $value){ + $key = ($this->OPTIONS['CASELESS']) ? strtolower(trim($key)) : trim($key); + if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $key) && $value !== null ) { + $this->_vars[$key] = $value; + } + } + } + else { + if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k) && $v !== null) { + if ($this->OPTIONS['CASELESS']) $k = strtolower($k); + $this->_vars[trim($k)] = $v; + } + else { + return false; + } + } + return true; + } + + /** + * FUNCTION: setInclude + * + * Sets dynamic includes to be used by the template + * If $k is an array, then it will treat it as an associative array + * using the keys as variable names and the values as variable values. + * + * @param mixed $k key to define variable name + * @param mixed $v variable to assign to $k + * @return boolean true/false + * @access public + */ + + function setInclude($k, $v = null) { + if(is_array($k)) { + foreach($k as $key => $val) { + $this->_dyninclude[$key] = $val; + } + } else { + $this->_dyninclude[$k] = $v; + } + + return true; + } + + /** + * FUNCTION: unsetVar + * + * Unsets a variable which has already been set + * Parse in all vars wanted for deletion in seperate parametres + * + * @param string var name to remove use: vlibTemplate::unsetVar(var[, var..]) + * @return boolean true/false returns true unless called with 0 params + * @access public + */ + function unsetVar () { + $num_args = func_num_args(); + if ($num_args < 1) return false; + + for ($i = 0; $i < $num_args; $i++) { + $var = func_get_arg($i); + if ($this->OPTIONS['CASELESS']) $var = strtolower($var); + if (!preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $var)) continue; + unset($this->_vars[$var]); + } + return true; + } + + /** + * FUNCTION: getVars + * + * Gets all vars currently set in global namespace. + * + * @return array + * @access public + */ + function getVars () { + if (empty($this->_vars)) return false; + return $this->_vars; + } + + /** + * FUNCTION: getVar + * + * Gets a single var from the global namespace + * + * @return var + * @access public + */ + function getVar ($var) { + if ($this->OPTIONS['CASELESS']) $var = strtolower($var); + if (empty($var) || !isset($this->_vars[$var])) return false; + return $this->_vars[$var]; + } + + /** + * FUNCTION: setContextVars + * + * sets the GLOBAL_CONTEXT_VARS + * + * @return true + * @access public + */ + function setContextVars () { + $_phpself = @$GLOBALS['HTTP_SERVER_VARS']['PHP_SELF']; + $_pathinfo = @$GLOBALS['HTTP_SERVER_VARS']['PATH_INFO']; + $_request_uri = @$GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI']; + $_qs = @$GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']; + + // the following fixes bug of $PHP_SELF on Win32 CGI and IIS. + $_self = (!empty($_pathinfo)) ? $_pathinfo : $_phpself; + $_uri = (!empty($_request_uri)) ? $_request_uri : $_self.'?'.$_qs; + + $this->setvar('__SELF__', $_self); + $this->setvar('__REQUEST_URI__', $_uri); + return true; + } + + /** + * FUNCTION: setLoop + * + * Builds the loop construct for use with . + * + * @param string $k string to define loop name + * @param array $v array to assign to $k + * @return boolean true/false + * @access public + */ + function setLoop ($k,$v) { + if (is_array($v) && preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k)) { + $k = ($this->OPTIONS['CASELESS']) ? strtolower(trim($k)) : trim($k); + $this->_arrvars[$k] = array(); + if ($this->OPTIONS['SET_LOOP_VAR'] && !empty($v)) $this->setvar($k, 1); + if (($this->_arrvars[$k] = $this->_arrayBuild($v)) == false) { + vlibTemplateError::raiseError('VT_WARNING_INVALID_ARR',WARNING,$k); + } + } + return true; + } + + /** + * FUNCTION: setDbLoop [** EXPERIMENTAL **] + * + * Function to create a loop from a Db result resource link. + * + * @param string $loopname to commit loop. If not set, will use last loopname set using newLoop() + * @param string $result link to a Db result resource + * @param string $db_type, type of db that the result resource belongs to. + * @return boolean true/false + * @access public + */ + function setDbLoop ($loopname, $result, $db_type='MYSQL') { + $db_type = strtoupper($db_type); + if (!in_array($db_type, $this->allowed_loop_dbs)) { + vlibTemplateError::raiseError('VT_WARNING_INVALID_LOOP_DB',WARNING, $db_type); + return false; + } + + $loop_arr = array(); + switch ($db_type) { + + case 'MYSQL': + if (get_resource_type($result) != 'mysql result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = mysql_fetch_assoc($result)) { + $loop_arr[] = $r; + } + break; + + case 'POSTGRESQL': + if (get_resource_type($result) != 'pgsql result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + + $nr = (function_exists('pg_num_rows')) ? pg_num_rows($result) : pg_numrows($result); + + for ($i=0; $i < $nr; $i++) { + $loop_arr[] = pg_fetch_array($result, $i, PGSQL_ASSOC); + } + break; + + case 'INFORMIX': + if (!$result) { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = ifx_fetch_row($result, 'NEXT')) { + $loop_arr[] = $r; + } + break; + + case 'INTERBASE': + if (get_resource_type($result) != 'interbase result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = ibase_fetch_row($result)) { + $loop_arr[] = $r; + } + break; + + case 'INGRES': + if (!$result) { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = ingres_fetch_array(INGRES_ASSOC, $result)) { + $loop_arr[] = $r; + } + break; + + case 'MSSQL': + if (get_resource_type($result) != 'mssql result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = mssql_fetch_array($result)) { + $loop_arr[] = $r; + } + break; + + case 'MSQL': + if (get_resource_type($result) != 'msql result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while($r = msql_fetch_array($result, MSQL_ASSOC)) { + $loop_arr[] = $r; + } + break; + + case 'OCI8': + if (get_resource_type($result) != 'oci8 statement') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while(OCIFetchInto($result, &$r, OCI_ASSOC+OCI_RETURN_LOBS)) { + $loop_arr[] = $r; + } + break; + + case 'ORACLE': + if (get_resource_type($result) != 'oracle Cursor') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while(ora_fetch_into($result, &$r, ORA_FETCHINTO_ASSOC)) { + $loop_arr[] = $r; + } + break; + + case 'OVRIMOS': + if (!$result) { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + while(ovrimos_fetch_into($result, &$r, 'NEXT')) { + $loop_arr[] = $r; + } + break; + + case 'SYBASE': + if (get_resource_type($result) != 'sybase-db result') { + vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE',WARNING, $db_type); + return false; + } + + while($r = sybase_fetch_array($result)) { + $loop_arr[] = $r; + } + break; + } + $this->setLoop($loopname, $loop_arr); + return true; + } + + /** + * FUNCTION: newLoop + * + * Sets the name for the curent loop in the 3 step loop process. + * + * @param string $name string to define loop name + * @return boolean true/false + * @access public + */ + function newLoop ($loopname) { + if (preg_match('/^[a-z_]+[a-z0-9_]*$/i', $loopname)) { + $this->_currloopname[$loopname] = $loopname; + $this->_currloop[$loopname] = array(); + return true; + } + else { + return false; + } + } + + /** + * FUNCTION: addRow + * + * Adds a row to the current loop in the 3 step loop process. + * + * @param array $row loop row to add to current loop + * @param string $loopname loop to which you want to add row, if not set will use last loop set using newLoop(). + * @return boolean true/false + * @access public + */ + function addRow ($row, $loopname=null) { + if (!$loopname) $loopname = $this->_currloopname[(count($this->_currloopname)-1)]; + + if (!isset($this->_currloop[$loopname]) || empty($this->_currloopname)) { + vlibTemplateError::raiseError('VT_WARNING_LOOP_NOT_SET',WARNING); + return false; + } + if (is_array($row)) { + $this->_currloop[$loopname][] = $row; + return true; + } + else { + return false; + } + } + + /** + * FUNCTION: addLoop + * + * Completes the 3 step loop process. This assigns the rows and resets + * the variables used. + * + * @param string $loopname to commit loop. If not set, will use last loopname set using newLoop() + * @return boolean true/false + * @access public + */ + function addLoop ($loopname=null) { + if ($loopname == null) { // add last loop used + if (!empty($this->_currloop)) { + foreach ($this->_currloop as $k => $v) { + $this->setLoop($k, $v); + unset($this->_currloop[$k]); + } + $this->_currloopname = array(); + return true; + } + else { + return false; + } + } + elseif (!isset($this->_currloop[$loopname]) || empty($this->_currloopname)) { // newLoop not yet envoked + vlibTemplateError::raiseError('VT_WARNING_LOOP_NOT_SET',WARNING); + return false; + } + else { // add a specific loop + $this->setLoop($loopname, $this->_currloop[$loopname]); + unset($this->_currloopname[$loopname], $this->_currloop[$loopname]); + } + return true; + } + + /** + * FUNCTION: unsetLoop + * + * Unsets a loop which has already been set. + * Can only unset top level loops. + * + * @param string loop to remove use: vlibTemplate::unsetLoop(loop[, loop..]) + * @return boolean true/false returns true unless called with 0 params + * @access public + */ + function unsetLoop () { + $num_args = func_num_args(); + if ($num_args < 1) return false; + + for ($i = 0; $i < $num_args; $i++) { + $var = func_get_arg($i); + if ($this->OPTIONS['CASELESS']) $var = strtolower($var); + if (!preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $var)) continue; + unset($this->_arrvars[$var]); + } + return true; + } + + + /** + * FUNCTION: reset + * + * Resets the vlibTemplate object. After using vlibTemplate::reset() you must + * use vlibTemplate::newTemplate(tmpl) to reuse, not passing in the options array. + * + * @return boolean true + * @access public + */ + function reset () { + $this->clearVars(); + $this->clearLoops(); + $this->_tmplfilename = null; + $this->_tmplfile = null; + $this->_tmplfilep = null; + $this->_tmploutput = null; + $this->_parsed = false; + $this->_unknowns = array(); + $this->_firstparsetime = null; + $this->_totalparsetime = null; + $this->_currloopname = null; + $this->_currloop = array(); + return true; + } + + /** + * FUNCTION: clearVars + * + * Unsets all variables in the template + * + * @return boolean true + * @access public + */ + function clearVars () { + $this->_vars = array(); + return true; + } + + /** + * FUNCTION: clearLoops + * + * Unsets all loops in the template + * + * @return boolean true + * @access public + */ + function clearLoops () { + $this->_arrvars = array(); + $this->_currloopname = null; + $this->_currloop = array(); + return true; + } + + /** + * FUNCTION: clearAll + * + * Unsets all variables and loops set using setVar/Loop() + * + * @return boolean true + * @access public + */ + function clearAll () { + $this->clearVars(); + $this->clearLoops(); + return true; + } + + /** + * FUNCTION: unknownsExist + * + * Returns true if unknowns were found after parsing. + * Function MUST be called AFTER one of the parsing functions to have any relevance. + * + * @return boolean true/false + * @access public + */ + function unknownsExist () { + return (!empty($this->_unknowns)); + } + + /** + * FUNCTION: unknowns + * + * Alias for unknownsExist. + * + * @access public + */ + function unknowns () { + return $this->unknownsExist(); + } + + /** + * FUNCTION: getUnknowns + * + * Returns an array of all unknown vars found when parsing. + * This function is only relevant after parsing a document. + * + * @return array + * @access public + */ + function getUnknowns () { + return $this->_unknowns; + } + + /** + * FUNCTION: setUnknowns + * + * Sets how you want to handle variables that were found in the + * template but not set in vlibTemplate using vlibTemplate::setVar(). + * + * @param string $arg ignore, remove, print, leave or comment + * @return boolean + * @access public + */ + function setUnknowns ($arg) { + $arg = strtolower(trim($arg)); + if (preg_match('/^ignore|remove|print|leave|comment$/', $arg)) { + $this->OPTIONS['UNKNOWNS'] = $arg; + return true; + } + return false; + } + + /** + * FUNCTION: setPath + * + * function sets the paths to use when including files. + * Use of this function: vlibTemplate::setPath(string path [, string path, ..]); + * i.e. if $tmpl is your template object do: $tmpl->setPath('/web/htdocs/templates','/web/htdocs/www'); + * with as many paths as you like. + * if this function is called without any arguments, it will just delete any previously set paths. + * + * @param string path (mulitple) + * @return bool success + * @access public + */ + function setPath () { + $num_args = func_num_args(); + if ($num_args < 1) { + $this->OPTIONS['INCLUDE_PATHS'] = array(); + return true; + } + for ($i = 0; $i < $num_args; $i++) { + $thispath = func_get_arg($i); + array_push($this->OPTIONS['INCLUDE_PATHS'], realpath($thispath)); + } + return true; + } + + /** + * FUNCTION: getParseTime + * + * After using one of the parse functions, this will allow you + * access the time taken to parse the template. + * see OPTION 'TIME_PARSE'. + * + * @return float time taken to parse template + * @access public + */ + function getParseTime () { + if ($this->OPTIONS['TIME_PARSE'] && $this->_parsed) { + return $this->_totalparsetime; + } + return false; + } + + + /** + * FUNCTION: fastPrint + * + * Identical to pparse() except that it uses output buffering w/ gz compression thus + * printing the output directly and compressed if poss. + * Will possibly if parsing a huge template. + * + * @access public + * @return boolean true/false + */ + function fastPrint () { + $ret = $this->_parse('ob_gzhandler'); + print($this->_tmploutput); + return $ret; + } + + + /** + * FUNCTION: pparse + * + * Calls parse, and then prints out $this->_tmploutput + * + * @access public + * @return boolean true/false + */ + function pparse () { + if (!$this->_parsed) $this->_parse(); + print($this->_tmploutput); + return true; + } + + /** + * FUNCTION: pprint + * + * Alias for pparse() + * + * @access public + */ + function pprint () { + return $this->pparse(); + } + + + /** + * FUNCTION: grab + * + * Returns the parsed output, ready for printing, passing to mail() ...etc. + * Invokes $this->_parse() if template has not yet been parsed. + * + * @access public + * @return boolean true/false + */ + function grab () { + if (!$this->_parsed) $this->_parse(); + return $this->_tmploutput; + } + + /*-----------------------------------------------------------------------------\ + | private functions | + \-----------------------------------------------------------------------------*/ + + /** + * FUNCTION: vlibTemplate + * + * vlibTemplate constructor. + * if $tmplfile has been passed to it, it will send to $this->newTemplate() + * + * @param string $tmplfile full path to template file + * @param array $options see above + * @return boolean true/false + * @access private + */ + function tpl ($tmplfile=null, $options=null) { + if (is_array($tmplfile) && $options == null) { + $options = $tmplfile; + unset($tmplfile); + } + + $this->VLIBTEMPLATE_ROOT = dirname(realpath(__FILE__)); + + if (is_array(vlibIni::vlibTemplate())) { + foreach (vlibIni::vlibTemplate() as $name => $val) { + $this->OPTIONS[$name] = $val; + } + } + + if (is_array($options)) { + foreach($options as $key => $val) { + $key = strtoupper($key); + if ($key == 'PATH') { + $this->setPath($val); + } + else { + $this->_setOption($key, strtolower($val)); + } + } + } + if($tmplfile) $this->newTemplate($tmplfile); + if ($this->OPTIONS['GLOBAL_CONTEXT_VARS']) $this->setContextVars(); + return true; + } + + /** FUNCTION: _getData + * + * function returns the text from the file, or if we're using cache, the text + * from the cache file. MUST RETURN DATA. + * @param string tmplfile contains path to template file + * @param do_eval used for included files. If set then this function must do the eval()'ing. + * @access private + * @return mixed data/string or boolean + */ + function _getData ($tmplfile, $do_eval=false) { + //check the current file depth + if ($this->_includedepth > $this->OPTIONS['MAX_INCLUDES'] || $tmplfile == false) { + return; + } + else { + if ($this->_debug) array_push ($this->_debugIncludedfiles, $tmplfile); + if ($do_eval) { + array_push($this->_currentincludedir, dirname($tmplfile)); + $this->_includedepth++; + } + } + + + if($this->_cache && $this->_checkCache($tmplfile)) { // cache exists so lets use it + $data = fread($fp = fopen($this->_cachefile, 'r'), filesize($this->_cachefile)); + fclose($fp); + } + else { // no cache lets parse the file + $data = fread($fp = fopen($tmplfile, 'r'), filesize($tmplfile)); + fclose($fp); + + $regex = '/(<|<\/|{|{\/|){1}'; + $regex.= '/ie'; + //$regex.= '([\r\n|\n|\r])?/ie'; + $data = preg_replace($regex,"\$this->_parseTag(array('\\0','\\1','\\2','\\3','\\4','\\5','\\6','\\7','\\8','\\9'));",$data); + + if ($this->_cache) { // add cache if need be + $this->_createCache($data); + } + } + + // now we must parse the $data and check for any 's + if ($this->_debug) $this->doDebugWarnings(file($tmplfile), $tmplfile); + + if ($do_eval) { + $success = @eval('?>'.$data.'_includedepth--; + array_pop($this->_currentincludedir); + return $success; + } + else { + return $data; + } + + } + + /** + * FUNCTION: _fileSearch + * + * Searches for all possible instances of file { $file } + * + * @param string $file path of file we're looking for + * @access private + * @return mixed fullpath to file or boolean false + */ + function _fileSearch ($file) { + $filename = basename($file); + $filepath = dirname($file); + + // check fullpath first.. + $fullpath = $filepath.'/'.$filename; + if (is_file($fullpath)) return $fullpath; + + // ..then check for relative path for current directory.. + if (!empty($this->_currentincludedir)) { + $currdir = $this->_currentincludedir[(count($this->_currentincludedir) -1)]; + $relativepath = realpath($currdir.'/'.$filepath.'/'.$filename); + if (is_file($relativepath)) { + array_push ($this->_currentincludedir, dirname($relativepath)); + return $relativepath; + } + } + + // ..then check for relative path for all additional given paths.. + if (!empty($this->OPTIONS['INCLUDE_PATHS'])) { + foreach ($this->OPTIONS['INCLUDE_PATHS'] as $currdir) { + $relativepath = realpath($currdir.'/'.$filepath.'/'.$filename); + if (is_file($relativepath)) { + return $relativepath; + } + } + } + + // ..then check path from TEMPLATE_DIR.. + if (!empty($this->OPTIONS['TEMPLATE_DIR'])) { + $fullpath = realpath($this->OPTIONS['TEMPLATE_DIR'].'/'.$filepath.'/'.$filename); + if (is_file($fullpath)) return $fullpath; + } + + // ..then check relative path from executing php script.. + $fullpath = realpath($filepath.'/'.$filename); + if (is_file($fullpath)) return $fullpath; + + // ..then check path from template file. + if (!empty($this->VLIBTEMPLATE_ROOT)) { + $fullpath = realpath($this->VLIBTEMPLATE_ROOT.'/'.$filepath.'/'.$filename); + if (is_file($fullpath)) return $fullpath; + } + + return false; // uh oh, file not found + } + + /** + * FUNCTION: _arrayBuild + * + * Modifies the array $arr to add Template variables, __FIRST__, __LAST__ ..etc + * if $this->OPTIONS['LOOP_CONTEXT_VARS'] is true. + * Used by $this->setloop(). + * + * @param array $arr + * @return array new look array + * @access private + */ + function _arrayBuild ($arr) { + if (is_array($arr) && !empty($arr)) { + $arr = array_values($arr); // to prevent problems w/ non sequential arrays + for ($i = 0; $i < count($arr); $i++) { + if(!is_array($arr[$i])) return false; + foreach ($arr[$i] as $k => $v) { + unset($arr[$i][$k]); + if ($this->OPTIONS['CASELESS']) $k = strtolower($k); + if (preg_match('/^[0-9]+$/', $k)) $k = '_'.$k; + + if (is_array($v)) { + if (($arr[$i][$k] = $this->_arrayBuild($v)) == false) return false; + } + else { // reinsert the var + $arr[$i][$k] = $v; + } + } + if ($this->OPTIONS['LOOP_CONTEXT_VARS']) { + if ($i == 0) $arr[$i]['__FIRST__'] = true; + if (($i + 1) == count($arr)) $arr[$i]['__LAST__'] = true; + if ($i != 0 && (($i + 1) < count($arr))) $arr[$i]['__INNER__'] = true; + if (is_int(($i+1) / 2)) $arr[$i]['__EVEN__'] = true; + if (!is_int(($i+1) / 2)) $arr[$i]['__ODD__'] = true; + $arr[$i]['__ROWNUM__'] = ($i + 1); + } + } + return $arr; + } + elseif (empty($arr)) { + return true; + } + } + + /** + * FUNCTION: _parseIf + * returns a string used for parsing in tmpl_if statements. + * + * @param string $varname + * @param string $value + * @param string $op + * @param string $namespace current namespace + * @access private + * @return string used for eval'ing + */ + function _parseIf ($varname, $value=null, $op=null, $namespace=null) { + if (isset($namespace)) $namespace = substr($namespace, 0, -1); + $comp_str = ''; // used for extended if statements + + // work out what to put on the end id value="whatever" is used + if (isset($value)) { + + // add the correct operator depending on whether it's been specified or not + if (!empty($op)) { + if (in_array($op, $this->allowed_if_ops)) { + $comp_str .= $op; + } + else { + vlibTemplateError::raiseError('VT_WARNING_INVALID_IF_OP', WARNING, $op); + } + } + else { + $comp_str .= '=='; + } + + // now we add the value, if it's numeric, then we leave the quotes off + if (is_numeric($value)) { + $comp_str .= $value; + } + else { + $comp_str .= '\''.$value.'\''; + } + } + + if (count($this->_namespace) == 0 || $namespace == 'global') return '$this->_vars[\''.$varname.'\']'.$comp_str; + $retstr = '$this->_arrvars'; + $numnamespaces = count($this->_namespace); + for ($i=0; $i < $numnamespaces; $i++) { + if ($this->_namespace[$i] == $namespace || (($i + 1) == $numnamespaces && !empty($namespace))) { + $retstr .= "['".$namespace."'][\$_".$i."]"; + break 1; + } + else { + $retstr .= "['".$this->_namespace[$i]."'][\$_".$i."]"; + } + } + if ($this->OPTIONS['GLOBAL_VARS'] && empty($namespace)) { + return '(('.$retstr.'[\''.$varname.'\'] !== null) ? '.$retstr.'[\''.$varname.'\'] : $this->_vars[\''.$varname.'\'])'.$comp_str; + } + else { + return $retstr."['".$varname."']".$comp_str; + } + } + + + /** + * FUNCTION: _parseLoop + * returns a string used for parsing in tmpl_loop statements. + * + * @param string $varname + * @access private + * @return string used for eval'ing + */ + function _parseLoop ($varname) { + array_push($this->_namespace, $varname); + $tempvar = count($this->_namespace) - 1; + $retstr = "for (\$_".$tempvar."=0 ; \$_".$tempvar." < count(\$this->_arrvars"; + for ($i=0; $i < count($this->_namespace); $i++) { + $retstr .= "['".$this->_namespace[$i]."']"; + if ($this->_namespace[$i] != $varname) $retstr .= "[\$_".$i."]"; + } + return $retstr."); \$_".$tempvar."++) {"; + } + + /** + * FUNCTION: _parseVar + * + * returns a string used for parsing in tmpl_var statements. + * + * @param string $wholetag + * @param string $tag + * @param string $varname + * @param string $escape + * @param string $format + * @param string $namespace + * @access private + * @return string used for eval'ing + */ + function _parseVar ($wholetag, $tag, $varname, $escape, $format, $namespace) { + if (!empty($namespace)) $namespace = substr($namespace, 0, -1); + $wholetag = stripslashes($wholetag); + + if (count($this->_namespace) == 0 || $namespace == 'global') { + $var1 = '$this->_vars[\''.$varname.'\']'; + } + else { + $var1build = "\$this->_arrvars"; + $numnamespaces = count($this->_namespace); + for ($i=0; $i < $numnamespaces; $i++) { + if ($this->_namespace[$i] == $namespace || (($i + 1) == $numnamespaces && !empty($namespace))) { + $var1build .= "['".$namespace."'][\$_".$i."]"; + break 1; + } + else { + $var1build .= "['".$this->_namespace[$i]."'][\$_".$i."]"; + } + } + $var1 = $var1build . "['$varname']"; + if ($this->OPTIONS['GLOBAL_VARS'] && empty($namespace)) { + $var2 = '$this->_vars[\''.$varname.'\']'; + } + } + + $beforevar = ''; + $aftervar = ''; + if (!empty($escape)&& isset($this->ESCAPE_TAGS[$escape])) { + $beforevar .= $this->ESCAPE_TAGS[$escape]['open']; + $aftervar = $this->ESCAPE_TAGS[$escape]['close'] . $aftervar; + } + + if (!empty($format)&& isset($this->FORMAT_TAGS[$format])) { + $beforevar .= $this->FORMAT_TAGS[$format]['open']; + $aftervar = $this->FORMAT_TAGS[$format]['close'] . $aftervar; + } + + // build return values + $retstr = 'if ('.$var1.' !== null) { '; + $retstr .= 'print('.$beforevar.$var1.$aftervar.'); '; + $retstr .= '}'; + + if (@$var2) { + $retstr .= ' elseif ('.$var2.' !== null) { '; + $retstr .= 'print('.$beforevar.$var2.$aftervar.'); '; + $retstr .= '}'; + } + + switch (strtolower($this->OPTIONS['UNKNOWNS'])) { + case 'comment': + $comment = addcslashes('', '', $wholetag).'//-->', '"'); + $retstr .= ' else { print("'.$comment.'"); $this->_setUnknown("'.$varname.'"); }'; + return $retstr; + break; + case 'leave': + $retstr .= ' else { print("'.addcslashes($wholetag, '"').'"); $this->_setUnknown("'.$varname.'"); }'; + return $retstr; + break; + case 'print': + $retstr .= ' else { print("'.htmlspecialchars($wholetag, ENT_QUOTES).'"); $this->_setUnknown("'.$varname.'"); }'; + return $retstr; + break; + + case 'ignore': + return $retstr; + break; + case 'remove': + default: + $retstr .= ' else { $this->_setUnknown("'.$varname.'"); }'; + return $retstr; + break; + } + } + + /** + * FUNCTION: _parseTag + * takes values from preg_replace in $this->_intparse() and determines + * the replace string. + * + * @param array $args array of all matches found by preg_replace + * @access private + * @return string replace values + */ + function _parseTag ($args) { + $wholetag = $args[0]; + $openclose = $args[1]; + $tag = strtolower($args[2]); + $newline = $args[9]; + //echo "1#$newline#2"; + + if ($tag == 'else') return ''.$newline; + if ($tag == 'tmpl_include') return $wholetag; // ignore tmpl_include tags + + if (preg_match("/^<\/|{\/|
{tmpl_var name='uid_txt'}:
{tmpl_var name='gid_txt'}:
{tmpl_var name='dir_txt'}: