diff --git a/src/CloudFlare/Api.php b/src/CloudFlare/Api.php index 3ebec56..4e9db6c 100644 --- a/src/CloudFlare/Api.php +++ b/src/CloudFlare/Api.php @@ -16,6 +16,14 @@ class Api { + /** + * Endpoint for a hosting partner + */ + const ENDPOINT_HOSTING_PARTNER = 'https://api.cloudflare.com/host-gw.html'; + /** + * Default API endpoint + */ + const ENDPOINT_DEFAULT = 'https://api.cloudflare.com/client/v4/%s'; /** * Default permissions level * @var array @@ -46,25 +54,46 @@ class Api */ private $permissions = null; + /** + * Default API endpoint + */ + protected $endpoint = self::ENDPOINT_DEFAULT; + /** * Make a new instance of the API client * This can be done via providing the email address and api key as seperate parameters * or by passing in an already instantiated object from which the details will be extracted + * + * Signature 1: + * @param $arg1 Object client object + * + * Signature 2: + * @param $arg1 string hosting partner key + * + * Signature 3: + * @param $arg1 string user email + * @param $arg2 string user auth key */ - public function __construct() + public function __construct($arg1, $arg2 = null, $arg3 = null) { - $num_args = func_num_args(); - if ($num_args === 1) { - $parameters = func_get_args(); - $client = $parameters[0]; - $this->email = $client->email; - $this->auth_key = $client->auth_key; - $this->curl_options = $client->curl_options; - $this->permissions = $client->permissions; - } else if ($num_args === 2) { - $parameters = func_get_args(); - $this->email = $parameters[0]; - $this->auth_key = $parameters[1]; + if (is_object($arg1)) { + $this->email = $arg1->email; + $this->auth_key = $arg1->auth_key; + $this->curl_options = $arg1->curl_options; + $this->permissions = $arg1->permissions; + } else if (is_null($arg2)) { + $this->auth_key = $arg1; + $this->endpoint = self::ENDPOINT_HOSTING_PARTNER; + } else { + if (false !== strpos($arg2, '@')) { + // reversed arguments + $this->email = $arg2; + $this->auth_key = $arg1; + } else { + $this->email = $arg1; + $this->auth_key = $arg2; + } + } } @@ -163,6 +192,24 @@ public function permissions() return $this->permissions; } + /** + * API in client mode + * + * @return bool + */ + public function isClient() { + return isset($this->email); + } + + /** + * API in provider mode + * + * @return bool + */ + public function isProvider() { + return !$this->isClient(); + } + /** * * @codeCoverageIgnore @@ -173,17 +220,17 @@ public function permissions() * @param string|null $method Type of method that should be used ('GET', 'POST', 'PUT', 'DELETE', 'PATCH') * @param string|null $permission_level Permission level required to preform the action */ - protected function request($path, array $data = null, $method = null, $permission_level = null) + protected function request($path = null, array $data = null, $method = null, $permission_level = null) { - if(!isset($this->email) || !isset($this->auth_key)) { + if(!isset($this->auth_key)) { throw new Exception('Authentication information must be provided'); return false; } - $data = (is_null($data) ? array() : $data); + $data = (is_null($data) ? array() : (array)$data); $method = (is_null($method) ? 'get' : $method); $permission_level = (is_null($permission_level) ? 'read' : $permission_level); - if(!is_null($this->permission_level[$permission_level])) { + if(!$this->isProvider() && !is_null($this->permission_level[$permission_level])) { if(!$this->permissions) { $this->permissions(); } @@ -198,7 +245,16 @@ protected function request($path, array $data = null, $method = null, $permissio return !is_null($val); }); - $url = 'https://api.cloudflare.com/client/v4/' . $path; + $headers = array('X-Auth-Key: ' . $this->auth_key); + if ($this->isProvider()) { + // no path is ever given, everything operates on host-gw.html + $data['host_key'] = $this->auth_key; + $data['act'] = $path; + } else { + $headers[] = "X-Auth-Email: " . $this->email; + } + + $url = sprintf($this->endpoint, $path); $default_curl_options = array( CURLOPT_VERBOSE => false, @@ -215,8 +271,6 @@ protected function request($path, array $data = null, $method = null, $permissio $curl_options = array_replace($default_curl_options, $this->curl_options); } - $headers = array("X-Auth-Email: {$this->email}", "X-Auth-Key: {$this->auth_key}"); - $ch = curl_init(); curl_setopt_array($ch, $curl_options); diff --git a/src/CloudFlare/Provider.php b/src/CloudFlare/Provider.php new file mode 100755 index 0000000..1181b43 --- /dev/null +++ b/src/CloudFlare/Provider.php @@ -0,0 +1,198 @@ + + * @version 1 + */ + + class Provider extends Api + { + public function __construct($key) { + parent::__construct($key); + // 5 seconds is too low for admin operations like full_zone_set + $this->setCurlOption(CURLOPT_TIMEOUT, 20); + } + + /** + * Create a new CloudFlare user + * + * @return string user key + */ + public function create_user($email, $pass, $username = null, $uniqid = null, $clobber = false) + { + $data = array( + 'cloudflare_email' => $email, + 'cloudflare_pass' => $pass, + 'clobber_unique_id' => $clobber + ); + + if (!is_null($username)) { + $data['cloudflare_username'] = $username; + } + + if (!is_null($uniqid)) { + $data['unique_id'] = $uniqid; + } + + return $this->post('user_create', $data); + } + + /** + * Setup a user's zone for CNAME hosting + * + * Set both $resolve_to and $subdomains to null for a full + * zone hosting by CF + * + * @param string $key 32-char key + * @param string $zone_name zone for which CloudFlare filters + * @param $resolve_to string|null target CNAME to resolve after filtering + * @param $subdomains array|null subdomains CF hosts + * @return object CF response + */ + public function zone_set($key, $zone_name, $resolve_to = null, array $subdomains = null) + { + $data = array( + 'user_key' => $key, + 'zone_name' => $zone_name + ); + $method = 'full_zone_set'; + // partial zone set + if ($resolve_to) { + $method = 'zone_set'; + $data['resolve_to'] = $resolve_to; + $data['subdomains'] = join(",", $subdomains); + } + + return $this->post($method, $data); + } + + /** + * Add a zone using the full setup method + * + * @param string $key 32-char auth key + * @param string $zone_name zone for which CF is authoritative + * @return object CF response + */ + public function full_zone_set($key, $zone_name) { + return $this->zone_set($key, $zone_name); + } + + /** + * Lookup a user's CF account information + * + * @param string $uniqid user unique id set during creation + * @return object CF response + */ + public function user_lookup($uniqid) { + return $this->post('user_lookup', $uniqid); + } + + public function user_auth($email, $passwd, $uniqid = null, $clobber = false) { + $data = array( + 'cloudflare_email' => $email, + 'cloudflare_pass' => $passwd, + 'unique_id' => $uniqid, + 'clobber_unique_id' => $clobber + ); + + $this->post('user_auth', $data); + } + + public function zone_lookup($key, $zone_name) { + $data = array( + 'user_key' => $key, + 'zone_name' => $zone_name + ); + return $this->post('zone_lookup', $data); + } + + public function zone_delete($key, $zone_name) { + $data = array( + 'user_key' => $key, + 'zone_name' => $zone_name + ); + return $this->post('zone_delete', $data); + } + + /** + * Renegerate your host key + * + * @XXX DANGEROUS!!! + * + * @return array|mixed + */ + public function host_key_regen() { + + return $this->post('host_key_regen'); + } + + /** + * List the domains currently active on CloudFlare for the given host + * + * Valid options are: + * limit + * offset + * zone_name + * sub_id + * zone_status + * sub_status + * + * Valid response zone_status codes: + * V: active + * D: deleted + * + * Valid subscription response status codes: + * V: active + * CNL: canceled + * + * @param array $options + * @return object + * + */ + public function zone_list(array $options = array()) { + $myoptions = array( + 'limit' => 100, + 'offset' => 0, + 'zone_name' => NULL, + 'sub_id' => NULL, + 'zone_status' => 'ALL', + 'sub_status' => 'ALL' + ); + + foreach (array_keys($myoptions) as $k) { + if (isset($options[$k])) { + $myoptions[$k] = $options[$k]; + } + } + + if (isset($options['sub_status'])) { + $valid = array('V','CNL','ALL'); + $status = strtoupper($options['sub_status']); + if (!in_array($status, $valid)) { + throw new \InvalidArgumentException("unknown sub_status `" . + $status ."'"); + } + $myoptions['sub_status'] = $status; + } + + if (isset($options['zone_status'])) { + $valid = array('V', 'D', 'ALL'); + $status = strtoupper($options['zone_status']); + if (!in_array($status, $valid)) { + throw new \InvalidArgumentException("unknown zone_status `" . + $status ."'"); + } + $myoptions['zone_status'] = $status; + } + + return $this->post('zone_list', $myoptions); + } + } diff --git a/src/CloudFlare/User.php b/src/CloudFlare/User.php index ddd33e2..81c470d 100644 --- a/src/CloudFlare/User.php +++ b/src/CloudFlare/User.php @@ -59,7 +59,7 @@ public function change_email($email, $email_confirm, $password) { $data = array( 'email' => $email, - 'confirm_email' => $confirm_email, + 'confirm_email' => $email_confirm, 'password' => $password ); return $this->put('user/email', $data); @@ -134,5 +134,4 @@ public function disable_two_factor_authentication($auth_token) ); return $this->delete('user/two_factor_authentication', $data); } - }