est fails for any reason other than API problems, //chances are the stored license was invalid. So we'll remove the local copy anyway. $this->resetState(); } } return $result; } /** * @return string|null */ public function getLicenseKey() { $this->lazyLoad(); if (is_string($this->licenseKey) && $this->licenseKey !== '') { return $this->licenseKey; } return null; } /** * @return string|null */ public function getSiteToken() { $this->lazyLoad(); if (is_string($this->siteToken) && $this->siteToken !== '') { return $this->siteToken; } return null; } /** * @return array */ public function getTokenHistory() { $this->lazyLoad(); return isset($this->tokenHistory) ? $this->tokenHistory : array(); } public function getProductSlug() { return $this->productSlug; } public function getApi() { return $this->api; } public function getSiteUrl() { if ( $this->licenseScope === self::LICENSE_SCOPE_NETWORK ) { $url = network_site_url(); } else { $url = site_url(); } return str_replace('https://', 'http://', $url); } /** * Register filters that will add license details to update requests and download URLs. * Add-ons can use this method to easily re-use the same license key as the main plugin. * * @param Puc_v4p11_Plugin_UpdateChecker $updateChecker */ public function addUpdateFiltersTo($updateChecker) { $updateChecker->addQueryArgFilter(array($this, 'filterUpdateChecks')); //Add license data to update download URL, or remove the URL if we don't have a license. $downloadFilter = array($this, 'filterUpdateDownloadUrl'); $updateChecker->addFilter('request_info_result', $downloadFilter, 20); $updateChecker->addFilter('pre_inject_update', $downloadFilter); $updateChecker->addFilter('pre_inject_info', $downloadFilter); } public function filterUpdateChecks($queryArgs) { if ( $this->getSiteToken() !== null ) { $queryArgs['license_token'] = $this->getSiteToken(); } if ( $this->getLicenseKey() !== null ) { $queryArgs['license_key'] = $this->getLicenseKey(); } $queryArgs['license_site_url'] = $this->getSiteUrl(); return $queryArgs; } /** * @param Puc_v4p11_Plugin_Info|null $pluginInfo * @param array $result * @return Puc_v4p11_Plugin_Info|null */ public function refreshLicenseFromPluginInfo($pluginInfo, $result) { $this->lazyLoad(); if ( !is_wp_error($result) && isset($result['response']['code']) && ($result['response']['code'] == 200) && !empty($result['body']) ){ $apiResponse = json_decode($result['body']); if ( is_object($apiResponse) && isset($apiResponse->license) ) { $this->license = $this->createLicenseObject($apiResponse->license); $this->save(); } } return $pluginInfo; } /** * Add license data to the update download URL if we have a valid license, * or remove the URL (thus disabling one-click updates) if we don't. * * @param Puc_v4p11_Plugin_Update|Puc_v4p11_Plugin_Info $pluginInfo * @return Puc_v4p11_Plugin_Update|Puc_v4p11_Plugin_Info */ public function filterUpdateDownloadUrl($pluginInfo) { if ( isset($pluginInfo, $pluginInfo->download_url) && !empty($pluginInfo->download_url) ) { $license = $this->getLicense(); if ( $license->canReceiveProductUpdates() ) { //Append license data to the download URL so that the server can verify it. $args = array_filter(array( 'license_key' => $this->getLicenseKey(), 'license_token' => $this->getSiteToken(), 'license_site_url' => $this->getSiteUrl(), )); $pluginInfo->download_url = add_query_arg($args, $pluginInfo->download_url); } else { //No downloads without a license! $pluginInfo->download_url = null; } } return $pluginInfo; } public function addCustomSchedule($schedules){ if ( $this->checkPeriod && ($this->checkPeriod > 0) ){ $scheduleName = 'every' . $this->checkPeriod . 'hours'; $schedules[$scheduleName] = array( 'interval' => $this->checkPeriod * 3600, 'display' => sprintf('Every %d hours', $this->checkPeriod), ); } return $schedules; } } class Wslm_LicenseManagerApi { private $apiUrl; public function __construct($apiUrl) { $this->apiUrl = $apiUrl; } public function getLicense($product, $key, $siteUrl = null) { $params = ($siteUrl !== null) ? array('site_url' => $siteUrl) : array(); return $this->get($this->endpoint($product, $key), $params); } public function licenseSite($product, $key, $siteUrl) { $params = array('site_url' => $siteUrl); return $this->post($this->endpoint($product, $key, null, 'license_site'), $params); } public function unlicenseSite($product, $key, $siteUrl) { $params = array('site_url' => $siteUrl); return $this->post($this->endpoint($product, $key, null, 'unlicense_site'), $params); } public function getLicenseByToken($product, $token, $siteUrl = null) { $params = ($siteUrl !== null) ? array('site_url' => $siteUrl) : array(); return $this->get($this->endpoint($product, null, $token), $params); } public function unlicenseSiteByToken($product, $token, $siteUrl) { $params = array('site_url' => $siteUrl); return $this->post($this->endpoint($product, null, $token, 'unlicense_site'), $params); } public function get($endpoint, $params = array()) { return $this->request('get', $endpoint, $params); } public function post($endpoint, $params = array()) { return $this->request('post', $endpoint, $params); } private function endpoint($product, $license = null, $token = null, $action = null) { $endpoint = '/products/' . urlencode($product) . '/licenses/'; $endpoint .= ($token !== null) ? 'bytoken/' . urlencode($token) : urlencode($license); if ( $action !== null ) { $endpoint .= '/' . $action; } return $endpoint; } /** * Send an API request. * * @param string $method * @param string $endpoint * @param array $params * @return Wslm_LicenseManagerApiResponse */ public function request($method, $endpoint, $params = array()) { $url = $this->getApiUrl($endpoint); $method = strtoupper($method); $args = array('method' => $method, 'timeout' => 30); if ( !empty($params) ) { if ( ($method === 'POST') || ($method === 'PUT') ) { $args['body'] = $params; } else { $url .= '?' . http_build_query($params, '', '&'); } } $response = wp_remote_request($url, $args); return new Wslm_LicenseManagerApiResponse($response); } private function getApiUrl($endpoint) { return rtrim($this->apiUrl, '/') . '/' . ltrim($endpoint, '/'); } } class Wslm_LicenseManagerApiResponse { public $response = null; public $httpCode; public $httpResponse; private $error = null; /** * @param array|WP_Error $httpResponse */ public function __construct($httpResponse) { $this->httpResponse = $httpResponse; $this->httpCode = intval(wp_remote_retrieve_response_code($httpResponse)); if ( is_wp_error($httpResponse) ) { $this->error = new WP_Error('api_request_failed', $httpResponse->get_error_message(), $this); $this->response = null; } else { //Attempt to parse the API response. Expect a JSON document. $data = json_decode(wp_remote_retrieve_body($httpResponse)); if ( $data === null ) { $this->error = new WP_Error( 'api_request_failed', 'Failed to parse the response returned by the licensing API (expected JSON).', $this ); } $this->response = $data; } } public function success() { return empty($this->error) && ($this->httpCode >= 200 && $this->httpCode < 400); } public function asWpError() { if ( $this->success() ) { return null; } if ( !empty($this->error) ) { return $this->error; } else if ( isset($this->response->error) ) { return new WP_Error($this->response->error->code, $this->response->error->message, $this); } else { return new WP_Error('http_' . $this->httpCode, 'HTTP error ' . $this->httpCode, $this); } } }