Implemented: FS#555 - Implemet traffic quota.
| | |
| | | `limit_cron` int(11) NOT NULL default '0', |
| | | `limit_cron_type` enum('url','chrooted','full') NOT NULL default 'url', |
| | | `limit_cron_frequency` int(11) NOT NULL default '5', |
| | | `limit_traffic_quota` int(11) NOT NULL default '-1', |
| | | `limit_client` int(11) NOT NULL default '0', |
| | | `parent_client_id` int(11) unsigned NOT NULL default '0', |
| | | `username` varchar(64) default NULL, |
| | |
| | | `limit_cron` int(11) NOT NULL default '0', |
| | | `limit_cron_type` enum('url','chrooted','full') NOT NULL default 'url', |
| | | `limit_cron_frequency` int(11) NOT NULL default '5', |
| | | `limit_traffic_quota` int(11) NOT NULL default '-1', |
| | | `limit_client` int(11) NOT NULL default '0', |
| | | PRIMARY KEY (`template_id`) |
| | | ) ENGINE=MyISAM AUTO_INCREMENT=1; |
| | |
| | | `system_user` varchar(255) default NULL, |
| | | `system_group` varchar(255) default NULL, |
| | | `hd_quota` bigint(20) NOT NULL default '0', |
| | | `traffic_quota` bigint(20) NOT NULL default '0', |
| | | `traffic_quota` bigint(20) NOT NULL default '-1', |
| | | `cgi` enum('n','y') NOT NULL default 'y', |
| | | `ssi` enum('n','y') NOT NULL default 'y', |
| | | `suexec` enum('n','y') NOT NULL default 'y', |
| | |
| | | `apache_directives` text, |
| | | `php_open_basedir` text, |
| | | `active` enum('n','y') NOT NULL default 'y', |
| | | `traffic_quota_lock` enum('n','y') NOT NULL default 'n', |
| | | PRIMARY KEY (`domain_id`) |
| | | ) ENGINE=MyISAM AUTO_INCREMENT=1; |
| | | |
| | |
| | | |
| | | // translation function for forms, tries the form wordbook first and if this fails, it tries the global wordbook |
| | | function lng($msg) { |
| | | global $app; |
| | | global $app,$conf; |
| | | |
| | | if(isset($this->wordbook[$msg])) { |
| | | return $this->wordbook[$msg]; |
| | |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | 'limit_traffic_quota' => array ( |
| | | 'datatype' => 'INTEGER', |
| | | 'formtype' => 'TEXT', |
| | | 'validators' => array ( 0 => array ( 'type' => 'ISINT', |
| | | 'errmsg'=> 'limit_traffic_quota_error_notint'), |
| | | ), |
| | | 'default' => '-1', |
| | | 'value' => '', |
| | | 'separator' => '', |
| | | 'width' => '10', |
| | | 'maxlength' => '10', |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | ################################## |
| | | # END Datatable fields |
| | | ################################## |
| | |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | 'limit_traffic_quota' => array ( |
| | | 'datatype' => 'INTEGER', |
| | | 'formtype' => 'TEXT', |
| | | 'validators' => array ( 0 => array ( 'type' => 'ISINT', |
| | | 'errmsg'=> 'limit_traffic_quota_error_notint'), |
| | | ), |
| | | 'default' => '-1', |
| | | 'value' => '', |
| | | 'separator' => '', |
| | | 'width' => '10', |
| | | 'maxlength' => '10', |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | ################################## |
| | | # END Datatable fields |
| | | ################################## |
| | |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | 'limit_traffic_quota' => array ( |
| | | 'datatype' => 'INTEGER', |
| | | 'formtype' => 'TEXT', |
| | | 'validators' => array ( 0 => array ( 'type' => 'ISINT', |
| | | 'errmsg'=> 'limit_traffic_quota_error_notint'), |
| | | ), |
| | | 'default' => '-1', |
| | | 'value' => '', |
| | | 'separator' => '', |
| | | 'width' => '10', |
| | | 'maxlength' => '10', |
| | | 'rows' => '', |
| | | 'cols' => '' |
| | | ), |
| | | ################################## |
| | | # END Datatable fields |
| | | ################################## |
| | |
| | | $wb["web_php_options_txt"] = 'PHP Options'; |
| | | $wb["limit_client_error"] = 'The max. number of clients is reached.'; |
| | | $wb["limit_web_quota_txt"] = 'Web Quota'; |
| | | $wb["limit_traffic_quota_txt"] = 'Traffic Quota'; |
| | | $wb["limit_trafficquota_error_notint"] = 'Traffic Quota must be a number.'; |
| | | ?> |
| | |
| | | $wb["limit_cron_error_frequency"] = 'The cron frequency limit must be a number.'; |
| | | $wb["error_template_name_empty"] = 'Please enter a Template name'; |
| | | $wb["limit_web_quota_txt"] = 'Web Quota'; |
| | | $wb["limit_traffic_quota_txt"] = 'Traffic Quota'; |
| | | $wb["limit_trafficquota_error_notint"] = 'Traffic Quota must be a number.'; |
| | | ?> |
| | |
| | | $wb["limit_client_error"] = 'The max. number of clients is reached.'; |
| | | $wb["limit_client_error_positive"] = 'The number of clients must be > 0'; |
| | | $wb["limit_web_quota_txt"] = 'Web Quota'; |
| | | $wb["limit_traffic_quota_txt"] = 'Traffic Quota'; |
| | | $wb["limit_trafficquota_error_notint"] = 'Traffic Quota must be a number.'; |
| | | ?> |
| | |
| | | <label for="limit_cron_frequency">{tmpl_var name='limit_cron_frequency_txt'}</label> |
| | | <input name="limit_cron_frequency" id="limit_cron_frequency" value="{tmpl_var name='limit_cron_frequency'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> |
| | | </div> |
| | | <div class="ctrlHolder"> |
| | | <label for="limit_traffic_quota">{tmpl_var name='limit_traffic_quota_txt'}</label> |
| | | <input name="limit_traffic_quota" id="limit_traffic_quota" value="{tmpl_var name='limit_traffic_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> MB |
| | | </div> |
| | | </fieldset> |
| | | |
| | | <input type="hidden" name="id" value="{tmpl_var name='id'}"> |
| | |
| | | <label for="limit_cron_frequency">{tmpl_var name='limit_cron_frequency_txt'}</label> |
| | | <input name="limit_cron_frequency" id="limit_cron_frequency" value="{tmpl_var name='limit_cron_frequency'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> |
| | | </div> |
| | | <div class="ctrlHolder"> |
| | | <label for="limit_traffic_quota">{tmpl_var name='limit_traffic_quota_txt'}</label> |
| | | <input name="limit_traffic_quota" id="limit_traffic_quota" value="{tmpl_var name='limit_traffic_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> MB |
| | | </div> |
| | | </fieldset> |
| | | |
| | | <input type="hidden" name="id" value="{tmpl_var name='id'}"> |
| | |
| | | <label for="limit_cron_frequency">{tmpl_var name='limit_cron_frequency_txt'}</label> |
| | | <input name="limit_cron_frequency" id="limit_cron_frequency" value="{tmpl_var name='limit_cron_frequency'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> |
| | | </div> |
| | | <div class="ctrlHolder"> |
| | | <label for="limit_traffic_quota">{tmpl_var name='limit_traffic_quota_txt'}</label> |
| | | <input name="limit_traffic_quota" id="limit_traffic_quota" value="{tmpl_var name='limit_traffic_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" /> MB |
| | | </div> |
| | | </fieldset> |
| | | |
| | | <input type="hidden" name="id" value="{tmpl_var name='id'}"> |
| | |
| | | 'width' => '7', |
| | | 'maxlength' => '7' |
| | | ), |
| | | /* |
| | | 'traffic_quota' => array ( |
| | | 'datatype' => 'INTEGER', |
| | | 'formtype' => 'TEXT', |
| | |
| | | 'width' => '7', |
| | | 'maxlength' => '7' |
| | | ), |
| | | */ |
| | | 'cgi' => array ( |
| | | 'datatype' => 'VARCHAR', |
| | | 'formtype' => 'CHECKBOX', |
| | |
| | | $wb["ssl_organisation_error_regex"] = 'Invalid SSL Organisation. Valid characters are: a-z, 0-9 and .,-_'; |
| | | $wb["ssl_organistaion_unit_error_regex"] = 'Invalid SSL Organisation Unit. Valid characters are: a-z, 0-9 and .,-_'; |
| | | $wb["ssl_country_error_regex"] = 'Invalid SSL Country. Valid characters are: A-Z'; |
| | | |
| | | $wb["limit_web_quota_free_txt"] = 'Max. available Traffic Quota'; |
| | | ?> |
| | |
| | | <label for="hd_quota">{tmpl_var name='hd_quota_txt'}</label> |
| | | <input name="hd_quota" id="hd_quota" value="{tmpl_var name='hd_quota'}" size="7" maxlength="7" type="text" class="textInput formLengthLimit" /> MB |
| | | </div> |
| | | <!-- |
| | | <div class="ctrlHolder"> |
| | | <label for="traffic_quota">{tmpl_var name='traffic_quota_txt'}</label> |
| | | <input name="traffic_quota" id="traffic_quota" value="{tmpl_var name='traffic_quota'}" size="7" maxlength="7" type="text" class="textInput formLengthLimit" /> |
| | | <input name="traffic_quota" id="traffic_quota" value="{tmpl_var name='traffic_quota'}" size="7" maxlength="7" type="text" class="textInput formLengthLimit" /> MB |
| | | </div> |
| | | --> |
| | | <div class="ctrlHolder"> |
| | | <p class="label">{tmpl_var name='cgi_txt'}</p> |
| | | <div class="multiField"> |
| | |
| | | if($_SESSION["s"]["user"]["typ"] != 'admin') { |
| | | // Get the limits of the client |
| | | $client_group_id = $_SESSION["s"]["user"]["default_group"]; |
| | | $client = $app->db->queryOneRecord("SELECT limit_web_domain, default_webserver, parent_client_id, limit_web_quota FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); |
| | | $client = $app->db->queryOneRecord("SELECT limit_traffic_quota, limit_web_domain, default_webserver, parent_client_id, limit_web_quota FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); |
| | | |
| | | //* Check the website quota |
| | | if(isset($_POST["hd_quota"]) && $client["limit_web_quota"] >= 0) { |
| | |
| | | unset($tmp_quota); |
| | | } |
| | | |
| | | //* Check the traffic quota |
| | | if(isset($_POST["traffic_quota"]) && $client["limit_traffic_quota"] > 0) { |
| | | $tmp = $app->db->queryOneRecord("SELECT sum(traffic_quota) as trafficquota FROM web_domain WHERE domain_id != ".intval($this->id)." AND ".$app->tform->getAuthSQL('u')); |
| | | $trafficquota = $tmp["trafficquota"]; |
| | | $new_traffic_quota = intval($this->dataRecord["traffic_quota"]); |
| | | if(($trafficquota + $new_traffic_quota > $client["limit_traffic_quota"]) || ($new_traffic_quota == -1 && $client["limit_traffic_quota"] != -1)) { |
| | | $max_free_quota = floor($client["limit_traffic_quota"] - $trafficquota); |
| | | if($max_free_quota < 0) $max_free_quota = 0; |
| | | $app->tform->errorMessage .= $app->tform->lng("limit_traffic_quota_free_txt").": ".$max_free_quota." MB<br>"; |
| | | // Set the quota field to the max free space |
| | | $this->dataRecord["traffic_quota"] = $max_free_quota; |
| | | } |
| | | unset($tmp); |
| | | unset($tmp_quota); |
| | | } |
| | | |
| | | // When the record is updated |
| | | if($this->id > 0) { |
| | | // restore the server ID if the user is not admin and record is edited |
| | |
| | | } |
| | | } |
| | | |
| | | ####################################################################################################### |
| | | // enforce traffic quota (only the "master-server") |
| | | ####################################################################################################### |
| | | |
| | | if ($app->dbmaster == $app->db) { |
| | | |
| | | $current_month = date('Y-m'); |
| | | |
| | | //* Check website traffic quota |
| | | $sql = "SELECT sys_groupid,domain_id,domain,traffic_quota,traffic_quota_lock FROM web_domain WHERE traffic_quota > 0 and type = 'vhost'"; |
| | | $records = $app->db->queryAllRecords($sql); |
| | | if(is_array($records)) { |
| | | foreach($records as $rec) { |
| | | |
| | | $web_traffic_quota = $rec['traffic_quota']; |
| | | $domain = $rec['web_domain']; |
| | | |
| | | // get the client |
| | | /* |
| | | $client_group_id = $rec["sys_groupid"]; |
| | | $client = $app->db->queryOneRecord("SELECT limit_traffic_quota,parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); |
| | | $reseller = $app->db->queryOneRecord("SELECT limit_traffic_quota FROM client WHERE client_id = ".intval($client['parent_client_id'])); |
| | | |
| | | $client_traffic_quota = intval($client['limit_traffic_quota']); |
| | | $reseller_traffic_quota = intval($reseller['limit_traffic_quota']); |
| | | */ |
| | | |
| | | //* get the traffic |
| | | $tmp = $app->db->query("SELECT traffic_bytes FROM web_traffic WHERE traffic_date like '$current_month%' AND hostname = '$domain'"); |
| | | $web_traffic = $tmp['traffic_bytes']/1024/1024; |
| | | |
| | | //* Website is over quota, we will disable it |
| | | /*if( ($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) || |
| | | ($client_traffic_quota > 0 && $web_traffic > $client_traffic_quota) || |
| | | ($reseller_traffic_quota > 0 && $web_traffic > $reseller_traffic_quota)) {*/ |
| | | if($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) { |
| | | $app->db->datalogUpdate('web_domain', "traffic_quota_lock = 'y',active = 'n'", 'domain_id', $rec['domain_id']); |
| | | $app->log("Traffic quota for ".$rec['domain_id']." Exceeded. Disabling website.",LOGLEVEL_DEBUG); |
| | | } else { |
| | | //* unlock the website, if traffic is lower then quota |
| | | if($rec['traffic_quota_lock'] == 'y') { |
| | | $app->db->datalogUpdate('web_domain', "traffic_quota_lock = 'n',active = 'y'", 'domain_id', $rec['domain_id']); |
| | | $app->log("Traffic quota for ".$rec['domain_id']." ok again. Enabling website.",LOGLEVEL_DEBUG); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | die("finished.\n"); |
| | | ?> |
| | |
| | | } |
| | | } |
| | | */ |
| | | |
| | | public function diffrec($record_old, $record_new) { |
| | | $diffrec_full = array(); |
| | | $diff_num = 0; |
| | | |
| | | if(is_array($record_old) && count($record_old) > 0) { |
| | | foreach($record_old as $key => $val) { |
| | | // if(!isset($record_new[$key]) || $record_new[$key] != $val) { |
| | | if($record_new[$key] != $val) { |
| | | // Record has changed |
| | | $diffrec_full['old'][$key] = $val; |
| | | $diffrec_full['new'][$key] = $record_new[$key]; |
| | | $diff_num++; |
| | | } else { |
| | | $diffrec_full['old'][$key] = $val; |
| | | $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]; |
| | | $diff_num++; |
| | | } else { |
| | | $diffrec_full['new'][$key] = $val; |
| | | $diffrec_full['old'][$key] = $val; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return array('diff_num' => $diff_num, 'diff_rec' => $diffrec_full); |
| | | |
| | | } |
| | | |
| | | //** Function to fill the datalog with a full differential record. |
| | | public function datalogSave($db_table, $action, $primary_field, $primary_id, $record_old, $record_new) { |
| | | global $app,$conf; |
| | | |
| | | // Insert backticks only for incomplete table names. |
| | | if(stristr($db_table,'.')) { |
| | | $escape = ''; |
| | | } else { |
| | | $escape = '`'; |
| | | } |
| | | |
| | | $tmp = $this->diffrec($record_old, $record_new); |
| | | $diffrec_full = $tmp['diff_rec']; |
| | | $diff_num = $tmp['diff_num']; |
| | | unset($tmp); |
| | | |
| | | // Insert the server_id, if the record has a server_id |
| | | $server_id = (isset($record_old["server_id"]) && $record_old["server_id"] > 0)?$record_old["server_id"]:0; |
| | | if(isset($record_new["server_id"])) $server_id = $record_new["server_id"]; |
| | | |
| | | |
| | | if($diff_num > 0) { |
| | | //print_r($diff_num); |
| | | //print_r($diffrec_full); |
| | | $diffstr = $app->db->quote(serialize($diffrec_full)); |
| | | $username = $app->db->quote($_SESSION["s"]["user"]["username"]); |
| | | $dbidx = $primary_field.":".$primary_id; |
| | | |
| | | 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 ('".$db_table."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')"; |
| | | $app->db->query($sql); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | //** Inserts a record and saves the changes into the datalog |
| | | public function datalogInsert($tablename, $insert_data, $index_field) { |
| | | global $app; |
| | | |
| | | $old_rec = array(); |
| | | $this->query("INSERT INTO $tablename $insert_data"); |
| | | $index_value = $this->insertID(); |
| | | $new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'"); |
| | | $this->datalogSave($tablename, 'INSERT', $index_field, $index_value, $old_rec, $new_rec); |
| | | |
| | | return $index_value; |
| | | } |
| | | |
| | | //** Updates a record and saves the changes into the datalog |
| | | public function datalogUpdate($tablename, $update_data, $index_field, $index_value) { |
| | | global $app; |
| | | |
| | | $old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'"); |
| | | $this->query("UPDATE $tablename SET $update_data WHERE $index_field = '$index_value'"); |
| | | $new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'"); |
| | | $this->datalogSave($tablename, 'UPDATE', $index_field, $index_value, $old_rec, $new_rec); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | //** Deletes a record and saves the changes into the datalog |
| | | public function datalogDelete($tablename, $index_field, $index_value) { |
| | | global $app; |
| | | |
| | | $old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'"); |
| | | $this->query("DELETE FROM $tablename WHERE $index_field = '$index_value'"); |
| | | $new_rec = array(); |
| | | $this->datalogSave($tablename, 'DELETE', $index_field, $index_value, $old_rec, $new_rec); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | public function closeConn() |
| | | { |