diff --git a/application/classes/auth/osb.php b/application/classes/auth/osb.php index 78436096..e9ee4677 100644 --- a/application/classes/auth/osb.php +++ b/application/classes/auth/osb.php @@ -198,7 +198,7 @@ class Auth_OSB extends Auth_ORM { Session::instance()->set('token',$token); $user = ORM::factory('account',$mmto->account_id); - $user->log(sprintf('Token %s used for method %s',$mmto->token,$mmto->module_method->name())); + $user->log(sprintf('Token %s used for method %s [%s]',$mmto->token,$mmto->module_method->name(),Request::current()->param('id'))); } } } diff --git a/application/classes/ormosb.php b/application/classes/ormosb.php index a38e876c..e1a0b567 100644 --- a/application/classes/ormosb.php +++ b/application/classes/ormosb.php @@ -112,7 +112,12 @@ abstract class ORMOSB extends ORM { if (array_key_exists($column,$this->_table_columns)) { // If the column is a blob, we'll decode it automatically - if ($this->_table_columns[$column]['data_type'] == 'blob' AND (! isset($this->_table_columns[$column]['auto_convert']) OR ! $this->_table_columns[$column]['auto_convert'])) { + if ( + $this->_table_columns[$column]['data_type'] == 'blob' + AND ! is_null($this->_object[$column]) + AND ! isset($this->_changed[$column]) + AND (! isset($this->_table_columns[$column]['auto_convert']) OR ! $this->_table_columns[$column]['auto_convert']) + ) { // In case our blob hasnt been saved as one. try { @@ -128,7 +133,13 @@ abstract class ORMOSB extends ORM { } // If the column is a serialized object, we'll unserialize it. - if (in_array($column,$this->_serialize_column) AND (! isset($this->_table_columns[$column]['unserialized']) OR ! $this->_table_columns[$column]['unserialized'])) { + if ( + in_array($column,$this->_serialize_column) + AND is_string($this->_object[$column]) + AND ! is_null($this->_object[$column]) + AND ! isset($this->_changed[$column]) + AND (! isset($this->_table_columns[$column]['unserialized']) OR ! $this->_table_columns[$column]['unserialized']) + ) { // In case our object hasnt been saved as serialized. try { diff --git a/application/media/css/login.css b/application/media/css/login.css index baabd9e2..cecbce68 100644 --- a/application/media/css/login.css +++ b/application/media/css/login.css @@ -1,10 +1,11 @@ /** Login Style Sheet **/ table.login { + width: 5%; margin-left: auto; margin-right: auto; - background-color: #F9F9FA; - border: 1px solid #AAAACC; + background-color: #FBFBFB; + border: 1px solid #A0A0A0; padding: 10px; } diff --git a/modules/host/classes/controller/task/host.php b/modules/host/classes/controller/task/host.php index a565a88e..8232f64c 100644 --- a/modules/host/classes/controller/task/host.php +++ b/modules/host/classes/controller/task/host.php @@ -12,6 +12,7 @@ class Controller_Task_Host extends Controller_Task { // Host Server Object private $hs; + private $so; public function __construct(Request $request, Response $response) { parent::__construct($request,$response); @@ -19,34 +20,83 @@ class Controller_Task_Host extends Controller_Task { // To make it easy for some methods, we'll load our service here switch (Request::current()->action()) { case 'getclient': - case 'getservice': + case 'getdomain': + case 'gettraffic': case 'provision': - $sid = $this->request->param('id'); + $this->so = ORM::factory('service',$this->request->param('id')); - $hso = ORM::factory('service',$sid)->plugin()->host_server; - require Kohana::find_file('vendor',$hso->provision_plugin); + if (! $this->so->loaded()) + throw new Kohana_Exception('Unknown service :sid',array(':sid'=>$this->request->param('id'))); + + $hso = $this->so->plugin()->host_server; $this->hs = new $hso->provision_plugin($hso); break; } } - /** - * Get Client Details from Host Server - */ - public function action_getclient() { - $sid = $this->request->param('id'); + public function save($index,$result) { + $p = $this->so->plugin(); - print_r((string)$this->hs->get_client(ORM::factory('service',$sid))); + // We need to use a new var to avoid Indirect modification of overloaded property errors. + $x = is_null($p->server_data) ? array() : $p->server_data; + $x[$p->host_server_id][$index] = serialize($result); + $p->server_data = $x; + + $x = is_null($p->server_data_date) ? array() : $p->server_data_date; + $x[$p->host_server_id][$index] = time(); + $p->server_data_date = $x; + + return $p->save(); } /** * Get Client Details from Host Server */ - public function action_getservice() { + public function action_getclient() { + $result = $this->hs->cmd_getclient($this->so); + $p = $this->so->plugin(); + + if ($result->loaded()) { + if (! isset($p->server_data[$p->host_server_id]['c']) OR (md5($p->server_data[$p->host_server_id]['c']) != md5(serialize($result)))) { + echo "WARNING: data changed on server"; + $this->save('c',$result); + } else + echo "NOTE: data same on server"; + + } else + print_r($result); + } + + /** + * Get Client Details from Host Server + */ + public function action_getdomain() { + $result = $this->hs->cmd_getdomain($this->so); + $p = $this->so->plugin(); + + if ($result->loaded()) { + if (! isset($p->server_data[$p->host_server_id]['d']) OR (md5($p->server_data[$p->host_server_id]['d']) != md5(serialize($result)))) { + echo "WARNING: data changed on server"; + $this->save('d',$result); + } else + echo "NOTE: data same on server"; + + } else + print_r($result); + } + + /** + * Get Domain Traffic + */ + public function action_gettraffic() { $sid = $this->request->param('id'); - print_r((string)$this->hs->get_service(ORM::factory('service',$sid))); + $result = $this->hs->cmd_gettraffic(ORM::factory('service',$sid)); + if ($result->gen_info) + print_r($result->gen_info->as_array()); + else + print_r((string)$result); } /** diff --git a/modules/host/classes/model/service/plugin/host.php b/modules/host/classes/model/service/plugin/host.php index 09ef11c7..ca3ca9e6 100644 --- a/modules/host/classes/model/service/plugin/host.php +++ b/modules/host/classes/model/service/plugin/host.php @@ -14,6 +14,9 @@ class Model_Service_Plugin_Host extends Model_Service_Plugin { protected $_table_name = 'service__hosting'; protected $_created_column = FALSE; protected $_updated_column = FALSE; + protected $_serialize_column = array( + 'server_data_date', + ); // Relationships protected $_has_one = array( @@ -33,6 +36,14 @@ class Model_Service_Plugin_Host extends Model_Service_Plugin { ), ); + public function rules() { + return array_merge(parent::rules(),array( + 'server_data_date'=>array( + array('ORMOSB::serialize_array',array(':model',':field',':value')), + ), + )); + } + // Required abstract functions public function admin_update() { return ''; @@ -52,11 +63,26 @@ class Model_Service_Plugin_Host extends Model_Service_Plugin { * to manage the domain. */ public function manage_button() { + $k = Random::char(); + Session::instance()->set('manage_button',$k); + + Script::add(array('type'=>'stdin','data'=>' + $(document).ready(function() { + var x=0; + $("button[name=submit]").click(function() { + if (x++) { alert("Please refresh the page"); return false; } + $.getJSON("'.URL::site('user/service/ajaxmanage/'.$this->service_id).'", { k: "'.$k.'" }, function(data) { + $.each(data, function(key, val) { $("#"+key).val(val); }); + }).error(function() { alert("There was a problem with the request"); return false; }).success(function() { $("#manage").submit(); }); + }); + });' + )); + // @todo Convert this to a Static_List display if ($this->service->queue == 'PROVISION') return _('To Be Provisioned'); - return ($this->host_username AND $this->host_password) ? $this->host_server->manage_button($this->host_username,$this->host_password,$this->name()) : ''; + return ($this->host_username AND $this->host_password) ? $this->host_server->manage_button($this->host_username,substr(md5($this->host_password),0,8),$this->name()) : ''; } } ?> diff --git a/modules/host/vendor/plesk.php b/modules/host/classes/plesk.php similarity index 68% rename from modules/host/vendor/plesk.php rename to modules/host/classes/plesk.php index 982b494b..b4ea47b2 100644 --- a/modules/host/vendor/plesk.php +++ b/modules/host/classes/plesk.php @@ -10,72 +10,23 @@ * @copyright (c) 2010 Deon George * @license http://dev.leenooks.net/license.html */ -class Plesk { +class Plesk implements Serializable { private $protocol = '1.6.0.1'; private $path = 'enterprise/control/agent.php'; // Service Object - private $hso; - private $packet; - private $xml; + protected $hso; + protected $packet; + protected $xml; + protected $_object; - // @todo Get this out of the DB - private $permissions = array( - 'cp_access'=>TRUE, - 'create_domains'=>FALSE, - 'manage_phosting'=>FALSE, - 'manage_php_safe_mode'=>FALSE, - 'manage_sh_access'=>FALSE, - 'manage_not_chroot_shell'=>FALSE, - 'manage_quota'=>TRUE, - 'manage_subdomains'=>TRUE, - 'manage_domain_aliases'=>FALSE, - 'manage_log'=>TRUE, - 'manage_anonftp'=>FALSE, - 'manage_crontab'=>FALSE, - 'change_limits'=>FALSE, - 'manage_dns'=>TRUE, - 'manage_webapps'=>FALSE, - 'manage_webstat'=>TRUE, - 'manage_maillists'=>TRUE, - 'manage_spamfilter'=>FALSE, - 'manage_virusfilter'=>FALSE, - 'allow_local_backups'=>FALSE, - 'allow_ftp_backups'=>TRUE, - 'remote_access_interface'=>FALSE, - 'site_builder'=>FALSE, - 'manage_performance'=>FALSE, - 'manage_dashboard'=>TRUE, - 'select_db_server'=>FALSE, - ); + public function serialize() { + return serialize($this->_object); + } + public function unserialize($s) { + $this->_object = unserialize($s); + } - // @todo Get this out of the DB - private $limits = array( - 'resource-policy'=>'notify', - 'max_dom'=>-1, - 'max_subdom'=>-1, - 'max_dom_aliases'=>-1, - 'disk_space_soft'=>-1, - 'disk_space'=>-1, - 'max_traffic_soft'=>-1, - 'max_traffic'=>-1, - 'max_wu'=>-1, - 'max_db'=>-1, - 'max_box'=>-1, - 'mbox_quota'=>51200000, - 'max_redir'=>-1, - 'max_mg'=>-1, - 'max_resp'=>-1, - 'max_maillists'=>-1, - 'max_webapps'=>0, - 'expiration'=>-1, - ); - - // @todo Get this out of the DB - private $ippool = array( - '111.67.13.20'=>'shared', - ); - - private $curlopts = array( + protected $curlopts = array( CURLOPT_CONNECTTIMEOUT => 60, CURLOPT_FAILONERROR => TRUE, CURLOPT_FOLLOWLOCATION => FALSE, @@ -85,7 +36,7 @@ class Plesk { CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYHOST => FALSE, CURLOPT_SSL_VERIFYPEER => FALSE, - CURLOPT_VERBOSE => TRUE, + CURLOPT_VERBOSE => FALSE, ); public function __construct(Model_Host_Server $hso) { @@ -94,7 +45,13 @@ class Plesk { $this->packet = $this->xml->add_node('packet','',array('version'=>$this->protocol)); } - private function server_command(XML $xml) { + protected function server_command(XML $xml) { + if (count($a=array_keys($xml->packet->as_array())) != 1) + throw kohana_exception('XML command malformed?'); + + // We need to find out the command key, so we can get the status result. + $key = array_shift($a); + $hs = $this->hso->prov_plugin_data(); $request = Request::factory(sprintf('%s/%s',$this->hso->manage_url,$this->path)) @@ -111,38 +68,64 @@ class Plesk { $response = $request->execute(); - return XML::factory(null,'plesk',$response->body()); + $result = XML::factory(null,'plesk',$response->body()); + return $result; + + return ($result->$key->get->result->status->value() == 'ok') ? $result->data : $result; + } + + protected function collapse(XML $xml) { + $result = array(); + + foreach ($xml->as_array() as $j=>$k) { + $v = $xml->$j->value(); + + if (count($k) > 1) { + foreach ($xml->get($j,1) as $k) + if (isset($k['name'][0])) + $result[$j][$k['name'][0]] = (isset($k['value'][0]) ? $k['value'][0] : ''); + else + $result[$j][] = $k; + + } elseif (! is_null($v)) + $result[$j] = $v; + else + $result[$j] = $this->collapse($xml->$j); + } + + if (array_key_exists('name',$result) AND array_key_exists('value',$result)) + $result = array($result['name']=>$result['value']); + + return $result; } /** * Get a Client Configuration */ - public function get_client(Model_Service $so) { - $client = $this->packet->add_node('client'); - $get = $client->add_node('get'); - $filter = $get->add_node('filter'); - $filter->add_node('login',$so->plugin()->host_username); - $dataset = $get->add_node('dataset'); - $dataset->add_node('gen_info'); - $dataset->add_node('stat'); - $dataset->add_node('permissions'); - $dataset->add_node('limits'); - $dataset->add_node('ippool'); - - return $this->server_command($this->xml); + public function cmd_getclient(Model_Service $so) { + $pco = new Plesk_Client($this->hso); + return $pco->cmd_getclient($so); } /** * Get a Server Configuration */ - public function get_service(Model_Service $so) { + public function cmd_getdomain(Model_Service $so) { + $pdo = new Plesk_Domain($this->hso); + return $pdo->cmd_getdomain($so); + } + + /** + * Get Domain Traffic + */ + public function cmd_gettraffic(Model_Service $so) { $client = $this->packet->add_node('domain'); - $get = $client->add_node('get'); + $get = $client->add_node('get_traffic'); $filter = $get->add_node('filter'); - $filter->add_node('domain-name',strtolower($so->name())); - $dataset = $get->add_node('dataset'); - $dataset->add_node('hosting'); - $dataset->add_node('limits'); + $filter->add_node('domain-name',strtolower($so->plugin()->name())); +# $filter->add_node('id',1); +# $get->add_node('since_date','2012-04-01'); +# $get->add_node('end_date','2012-04-02'); return $this->server_command($this->xml); } diff --git a/modules/host/classes/plesk/client.php b/modules/host/classes/plesk/client.php new file mode 100644 index 00000000..9ea580de --- /dev/null +++ b/modules/host/classes/plesk/client.php @@ -0,0 +1,105 @@ +array(), + 'stat'=>array(), + 'permissions' => array( + 'cp_access'=>TRUE, + 'create_domains'=>FALSE, + 'manage_phosting'=>FALSE, + 'manage_php_safe_mode'=>FALSE, + 'manage_sh_access'=>FALSE, + 'manage_not_chroot_shell'=>FALSE, + 'manage_quota'=>TRUE, + 'manage_subdomains'=>TRUE, + 'manage_domain_aliases'=>FALSE, + 'manage_log'=>TRUE, + 'manage_anonftp'=>FALSE, + 'manage_crontab'=>FALSE, + 'change_limits'=>FALSE, + 'manage_dns'=>TRUE, + 'manage_webapps'=>FALSE, + 'manage_webstat'=>TRUE, + 'manage_maillists'=>TRUE, + 'manage_spamfilter'=>FALSE, + 'manage_virusfilter'=>FALSE, + 'allow_local_backups'=>FALSE, + 'allow_ftp_backups'=>TRUE, + 'remote_access_interface'=>FALSE, + 'site_builder'=>FALSE, + 'manage_performance'=>FALSE, + 'manage_dashboard'=>TRUE, + 'select_db_server'=>FALSE, + ), + 'limits' => array( + 'resource-policy'=>'notify', + 'max_dom'=>-1, + 'max_subdom'=>-1, + 'max_dom_aliases'=>-1, + 'disk_space_soft'=>-1, + 'disk_space'=>-1, + 'max_traffic_soft'=>-1, + 'max_traffic'=>-1, + 'max_wu'=>-1, + 'max_db'=>-1, + 'max_box'=>-1, + 'mbox_quota'=>51200000, + 'max_redir'=>-1, + 'max_mg'=>-1, + 'max_resp'=>-1, + 'max_maillists'=>-1, + 'max_webapps'=>0, + 'expiration'=>-1, + ), + 'ippool' => array( + '111.67.13.20'=>'shared', + ), + ); + + /** + * Get a Client Configuration + */ + public function cmd_getclient(Model_Service $so) { + $items = array_keys($this->_template); + + $client = $this->packet->add_node('client'); + $get = $client->add_node('get'); + $filter = $get->add_node('filter'); + $filter->add_node('login',$so->plugin()->host_username); + $dataset = $get->add_node('dataset'); + foreach ($items as $k) + $dataset->add_node($k); + + $result = $this->server_command($this->xml); + + if ($result->client->get->result->status->value() != 'ok') + throw new Kohana_Exception('Unable to get PLESK Client data'); + + foreach ($items as $k) + foreach ($result->get($k) as $a=>$b) + $this->_object[$k] = $this->collapse($b); + + $this->_loaded = TRUE; + + return $this; + } + + public function loaded() { + return $this->_loaded; + } +} +?> diff --git a/modules/host/classes/plesk/domain.php b/modules/host/classes/plesk/domain.php new file mode 100644 index 00000000..d8799d8a --- /dev/null +++ b/modules/host/classes/plesk/domain.php @@ -0,0 +1,56 @@ +array(), + 'hosting'=>array(), + 'limits'=>array(), + 'user'=>array(), + ); + + /** + * Get a Client Configuration + */ + public function cmd_getdomain(Model_Service $so) { + $items = array_keys($this->_template); + + $domain = $this->packet->add_node('domain'); + $get = $domain->add_node('get'); + $filter = $get->add_node('filter'); + $filter->add_node('domain-name',strtolower($so->plugin()->name())); + $dataset = $get->add_node('dataset'); + foreach ($items as $k) + $dataset->add_node($k); + + $result = $this->server_command($this->xml); + + if ($result->domain->get->result->status->value() != 'ok') + throw new Kohana_Exception('Unable to get PLESK Domain data'); + + foreach ($items as $k) + foreach ($result->get($k) as $a=>$b) + $this->_object[$k] = $this->collapse($b); + + $this->_loaded = TRUE; + + return $this; + } + + public function loaded() { + return $this->_loaded; + } +} +?> diff --git a/modules/host/classes/service/host/plesk.php b/modules/host/classes/service/host/plesk.php index eb8b7097..21f4bb65 100644 --- a/modules/host/classes/service/host/plesk.php +++ b/modules/host/classes/service/host/plesk.php @@ -21,12 +21,12 @@ class Service_Host_Plesk extends Service_Host { $output .= Form::open( sprintf('%s/%s',$this->so->manage_url,'login_up.php3'), - array('target'=>'w24','method'=>'post') + array('target'=>'w24','method'=>'post','id'=>'manage') ); - $output .= Form::input($this->login_user_field,$u,array('type'=>'hidden')); - $output .= Form::input($this->login_pass_field,$p,array('type'=>'hidden')); - $output .= Form::button('submit',_('Manage'),array('class'=>'form_button')); + $output .= Form::input($this->login_user_field,$u,array('type'=>'hidden','id'=>'u')); + $output .= Form::input($this->login_pass_field,$p,array('type'=>'hidden','id'=>'p')); $output .= Form::close(); + $output .= Form::button('submit',_('Manage'),array('class'=>'form_button')); return $output; } diff --git a/modules/payment/classes/payment/bulk/ezypay.php b/modules/payment/classes/payment/bulk/ezypay.php index 9123f5e0..474b8391 100644 --- a/modules/payment/classes/payment/bulk/ezypay.php +++ b/modules/payment/classes/payment/bulk/ezypay.php @@ -67,6 +67,10 @@ class Payment_Bulk_Ezypay { $line = preg_replace("/\s+$/",'',$line); $array = explode("\t",$line); + // If we dont have a payment item for this fee, we'll continue. + if (! isset($payments[$array[3]])) + continue; + // Our commission fees // @todo This should be in a config file if (in_array($array[9],array(1,15))) diff --git a/modules/payment/views/payment/admin/addbulk/ezypay/body.php b/modules/payment/views/payment/admin/addbulk/ezypay/body.php index 932a9650..508b4d42 100644 --- a/modules/payment/views/payment/admin/addbulk/ezypay/body.php +++ b/modules/payment/views/payment/admin/addbulk/ezypay/body.php @@ -1,5 +1,5 @@ - display('id'); ?> + id,$o->display('id')); ?> display('date_payment'); ?> display('total_amt'); ?> display('fees_amt'); ?> diff --git a/modules/service/classes/controller/user/service.php b/modules/service/classes/controller/user/service.php index fb57549a..cd129bc7 100644 --- a/modules/service/classes/controller/user/service.php +++ b/modules/service/classes/controller/user/service.php @@ -12,10 +12,26 @@ */ class Controller_User_Service extends Controller_TemplateDefault_User { protected $secure_actions = array( + 'ajaxmanage'=>TRUE, 'list'=>TRUE, 'view'=>TRUE, ); + public function action_ajaxmanage() { + $this->auto_render = FALSE; + + $so = ORM::factory('service',$this->request->param('id')); + $k = Session::instance()->get_once('manage_button'); + + $o = array( + 'u'=>$so->plugin()->host_username ? $so->plugin()->host_username : strtolower($so->plugin()->name()), + 'p'=>(! $k OR ! $this->request->is_ajax() OR ! $so->loaded() OR ! isset($_REQUEST['k']) OR $k != $_REQUEST['k']) ? Random::char() : $so->plugin()->host_password, + ); + + $this->response->headers('Content-Type','application/json'); + $this->response->body(json_encode($o)); + } + /** * Show a list of services */ diff --git a/modules/ssl/views/ssl/admin/add_view.php b/modules/ssl/views/ssl/admin/add_view.php index 110ab052..31c30468 100644 --- a/modules/ssl/views/ssl/admin/add_view.php +++ b/modules/ssl/views/ssl/admin/add_view.php @@ -9,11 +9,11 @@ Valid From - sign_cert); ?> + sign_cert,TRUE); ?> Valid To - sign_cert); ?> + sign_cert,TRUE); ?> Serial Num