m_request_body = file_get_contents('php://input'); $this->m_input = json_decode(($this->m_request_body)); $this->db = new MeekroDB(DB_HOST, DB_USER, DB_PASS,DB_NAME); // from config file //enable exception $this->db->error_handler = false; $this->db->nonsql_error_handler = false; $this->db->throw_exception_on_error = true; $this->db->throw_exception_on_nonsql_error = true; } private function is_valid_input() { //if it's not a valid json if ( $this->m_input != FALSE && property_exists($this->m_input, "license") && property_exists($this->m_input, "mid") ){ if ( strlen($this->m_input->license) >= 10 && strlen($this->m_input->mid) >=10 ){ return true; } } $this->record_possible_hack(); return false; } private function is_legit_code() { $code = $this->m_input->license; $f = $this->db->query("SELECT * FROM volume WHERE code='$code'"); return count($f) == 1 ; } //record possible hack input //save ip, date, request header, and invalid inputs private function record_possible_hack() { $dump = new DumpHTTPRequestToString(); $req = $dump->execute(); $err = $this->db->insert("hack", array( "ip" => $this->get_client_ip(), "input" => $this->m_request_body, "request" => $req )); } private function fresh_registration() { $config = $this->get_license_config(); //inser it into database $license = [ 'code' => $this->m_input->license, 'mid' => $this->m_input->mid, 'seat' => 1, 'quota' => $this->get_license_quota() , 'config' => intVal($config["id"]), 'enabled' => 1, 'ip' => $this->get_client_ip() ]; try { $this->db->insert("register", $license); $this->send_config($config, $license); }catch (MeekroDBException $e){ $this->send_error("Failed to add registration, please try again later" ); } } private function get_exact_match() { $code = $this->m_input->license; $mid = $this->m_input->mid; $match = $this->db->query("SELECT * FROM register WHERE code='$code' AND mid='$mid';"); if (count($match) !=1 ){ return FALSE; }else{ return $match[0]; } } private function get_license_by_code() { $code = $this->m_input->license; $matches = $this->db->query("SELECT * FROM register WHERE code='$code';"); if (count($matches) < 1 ){ return FALSE; }else{ return $matches; } } private function quota_available($matches) { return count($matches) < $this->get_license_quota(); } private function allocate_seat($matches){ $seat = $this->find_empty_seat($matches); $config = $this->get_license_config(); $license = array( 'code' => $this->m_input->license, 'mid' => $this->m_input->mid, 'seat' => $seat, 'quota' => $this->get_license_quota() , 'config' => intVal($config["id"]), 'enabled' => 1, 'ip' => $this->get_client_ip() ); try { $this->db->insert("register",$license); $this->send_config($config, $license); }catch (MeekroDBException $e){ $this->send_error("Allocate Seats $seat failed"); } } private function find_empty_seat($matches) { for ($i=1; $i <= $this->get_license_quota(); $i++) { if ( $this->seats_occupied($matches, $i) ) continue; return $i; } } private function seats_occupied($matches, $seat) { for ($i=0; $i< count($matches); $i++){ if ( $matches[$i]["seat"] == $seat ) return true; } return false; } //main routine public function start_registration() { if (! $this->is_valid_input() ){ $this->send_error("Sorry, your input is invalid"); return; //stop everything } if (! $this->is_legit_code()) { $this->send_error("Sorry, Your license is not valid"); return; } //check mid see if a matched license code and mid already exist $license = $this->get_exact_match(); if ( $license != FALSE ){ //we found the match both license-code and machine-id //get existing config if ( $license['enabled'] == 1 ) { $existing_config = $this->get_config_by_id($license["config"]); $this->send_config($existing_config, $license); }else{ $this->send_error("Sorry, Your license is disabled"); } }else{ $licenses = $this->get_license_by_code(); if ( $licenses == FALSE ) {//not found $this->fresh_registration(); }else{//we found, existing records if ( $this->quota_available($licenses) ){ $this->allocate_seat($licenses); }else{ $this->send_error("Sorry, Your license has been fully allocated"); } } } } private function get_config_by_id($id) { $f= $this->db->query("SELECT * FROM servers WHERE id=$id"); return $f[0]; } private function send_config($config, $license) { $msg = "" ; if ($license["quota"] >1){ $msg = "Seat " . $license["seat"] . "/" . $license["quota"] . " has been allocated to you"; }else{ $msg = "Single user license registered sucessfully"; } $result= array( "success" => true, "type" => $config["type"], "host" => $config["host"], "port" => $config["port"], "username" => $config["user"], "password" => $config["pass"], "license" => $license["code"], "mid" => $license["mid"], "proxyDNS" => true, "enable" => true, "errMsg" => $msg, "link" => "https://hk-01.biukop.com/", "linkText" => "Check My IP", ); $myJSON = json_encode($result); echo $myJSON; } private function send_error($msg){ echo $msg; die(); } private function decode_pass($encrypt) { $buf = base64_decode($encrypt); if ( substr($buf, -3, 2) != "#!" ) return "invalid-encrypt"; $magic_digit = intVal(substr($buf, 2 , 1)); $pass = substr($buf,5, -$magic_digit); return $pass; } private function encode_pass($pass) { // prefix: "xxyxx"; Y is digit $magic_digit = $this->rand_digit(); $prefix = $this->build_prefix($magic_digit); $suffix = $this->build_suffix($magic_digit); //surffix yyyyy#!xx , max 9 return base64_encode($prefix . $pass . $suffix); } private function rand_char() { $pool="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+:{}|<>?[]\;,./"; $idx = rand(0, strlen($pool) -1 ); return substr($pool, $idx, 1); } private function rand_digit() { return rand(3,9); } private function build_prefix($magic_digit) { return $this->rand_char() . $this->rand_char() . "$magic_digit" . $this->rand_char() . $this->rand_char(); } private function build_suffix($magic_digit) { //$magic_digit >=3 $suffix = ""; for ($i=1; $i<= $magic_digit-3; $i++) { $suffix .= $this->rand_char(); } $suffix .= "#!"; $suffix .= $this->rand_char(); return $suffix; } private function get_client_ip () { //whether ip is from share internet if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip_address = $_SERVER['HTTP_CLIENT_IP']; } //whether ip is from proxy elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } //whether ip is from remote address else { $ip_address = $_SERVER['REMOTE_ADDR']; } return $ip_address; } private function get_license_quota() { $code = $this->m_input->license; $f = $this->db->query("SELECT * FROM volume WHERE code='$code'"); return intVal($f[0]["max"]); } private function get_license_config() { $code = $this->m_input->license; $f = $this->db->query("SELECT * FROM servers WHERE code='$code'"); return $f[0]; } public function test_password() { $encrypt = $this->encode_pass("superforex"); $pass1 = $this->decode_pass($encrypt); $pass = $this->decode_pass("Y2Q1ZDFzdXBlcmZvcmV4MTIjITU="); if ($pass != $pass1){ echo "wrong"; } } public function test_license_quota() { $this->m_input = new stdClass(); $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; $six = $this->get_license_quota(); if ($six != 6) echo "wrong: license quota"; } public function test_get_config() { $this->m_input = new stdClass(); $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; $config = $this->get_license_config(); } public function test_fresh_registration() { $this->m_input = new stdClass(); $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; $this->m_input->mid = "AFDAFDSAFDSAFSDAFSAFSDA"; $this->fresh_registration(); } public function test_licenses() { $this->m_input = new stdClass(); $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; $this->m_input->mid = "2-AFDAFDSAFDSAFSDAFSAFSDA"; $this->start_registration(); } public function test() { $this->m_input = new stdClass(); $this->m_input->license = "VOL"; $this->m_input->mid = "2-AFD"; $this->start_registration(); } } class DumpHTTPRequestToString { public function execute() { $data = sprintf( "%s %s %s %s\n\nHTTP headers:\n", $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL'], $_SERVER['REMOTE_ADDR'] ); foreach ($this->getHeaderList() as $name => $value) { $data .= $name . ': ' . $value . "\n"; } $data .= "\nRequest body:\n" . file_get_contents('php://input'); return $data; } private function getHeaderList() { $headerList = []; foreach ($_SERVER as $name => $value) { if (preg_match('/^HTTP_/',$name)) { // convert HTTP_HEADER_NAME to Header-Name $name = strtr(substr($name,5),'_',' '); $name = ucwords(strtolower($name)); $name = strtr($name,' ','-'); // add to list $headerList[$name] = $value; } } return $headerList; } } $bb = new LicenseRegistration(); $bb->start_registration(); //$bb->test(); ?>