PluginProbe
WP Reset / 1.86
WP Reset v1.86
trunk 1.0 1.1 1.11 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.77 1.80 1.81 1.82 1.83 1.84 1.85 1.86 1.90 All 42 releases
wp-reset / wp-reset-licensing.php

wp-reset-licensing.php in WP Reset 1.86, at wp-reset-licensing.php

545 lines 15.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WebFactory Licensing Manager
4 * (c) WebFactory Ltd
5 * www.webfactoryltd.com
6 */
7
8
9 if (false === class_exists('WF_Licensing')) {
10 class WF_Licensing
11 {
12 public $prefix = '';
13 private $licensing_servers = array();
14 private $version = '';
15 private $slug = '';
16 private $basename = '';
17 private $plugin_file = '';
18 private $js_folder = '';
19 protected $api_ver = 'v1/';
20 protected $valid_forever = '2035-01-01';
21 protected $unlimited_installs = 99999;
22 public $debug = false;
23
24
25 /**
26 * Init licensing by setting up various params and hooking into actions.
27 *
28 * @param array $params Prefix, licensing_servers, version, plugin_file, skip_hooks
29 *
30 * @return void
31 */
32 function __construct($params)
33 {
34 $this->prefix = trim($params['prefix']);
35 $this->licensing_servers = $params['licensing_servers'];
36 $this->version = trim($params['version']);
37 $this->slug = dirname(plugin_basename(trim($params['plugin_file'])));
38 $this->basename = plugin_basename(trim($params['plugin_file']));
39 $this->plugin_file = $params['plugin_file'];
40 $this->debug = !empty($params['debug']);
41
42 if ($params['js_folder']) {
43 $this->js_folder = trim($params['js_folder']);
44 } else {
45 $this->js_folder = plugin_dir_url($this->plugin_file) . 'js/';
46 }
47
48 if (empty($params['skip_hooks'])) {
49 register_activation_hook($this->plugin_file, array($this, 'activate_plugin'));
50 register_deactivation_hook($this->plugin_file, array($this, 'deactivate_plugin'));
51
52 add_action('init', array($this, 'init'));
53
54 add_action('wp_ajax_wf_licensing_' . $this->prefix . '_validate', array($this, 'validate_ajax'));
55 add_action('wp_ajax_wf_licensing_' . $this->prefix . '_save', array($this, 'save_ajax'));
56 add_action('wp_ajax_wf_licensing_' . $this->prefix . '_deactivate', array($this, 'deactivate_ajax'));
57 }
58
59 $this->log('__construct', $params, get_object_vars($this));
60 } // __construct
61
62
63 /**
64 * Actions performed on WP init action.
65 *
66 * @return void
67 */
68 function init()
69 {
70 if (is_admin()) {
71 $vars = array(
72 'prefix' => $this->prefix,
73 'debug' => $this->debug,
74 'nonce' => wp_create_nonce('wf_licensing_' . $this->prefix),
75 'licensing_endpoint' => $this->licensing_servers[0] . $this->api_ver,
76 'request_data' => array(
77 'action' => 'validate_license',
78 'license_key' => '',
79 'rand' => rand(1000, 9999),
80 'version' => $this->version,
81 'wp_version' => get_bloginfo('version'),
82 'site_url' => get_home_url(),
83 'site_title' => get_bloginfo('name'),
84 'meta' => array()
85 )
86 );
87
88 wp_enqueue_script('wf_licensing', $this->js_folder . 'wf-licensing.js', array(), 1.0, true);
89 wp_localize_script('wf_licensing', 'wf_licensing_' . $this->prefix, $vars);
90 }
91 } // init
92
93
94 /**
95 * Log message if debugging is enabled.
96 * Log file: /wp-content/wf-licensing.log
97 *
98 * @param string $message Message to write to log.
99 * @param mixed $data Optional, extra data to write to debug log.
100 *
101 * @return void
102 */
103 function log($message, ...$data)
104 {
105 if (!$this->debug) {
106 return;
107 }
108
109 $log_file = trailingslashit(WP_CONTENT_DIR) . 'wf-licensing.log';
110 $fp = fopen($log_file, 'a+');
111
112 fputs($fp, '[' . date('r') . '] ' . $this->prefix . ': ');
113 fputs($fp, (string) $message . PHP_EOL);
114 foreach ($data as $tmp) {
115 fputs($fp, var_export($tmp, true) . PHP_EOL);
116 }
117
118 fputs($fp, PHP_EOL);
119 fclose($fp);
120 } // log
121
122
123 /**
124 * Fetches license details from the database.
125 *
126 * @param string $key If set returns only requested options key.
127 *
128 * @return string
129 */
130 function get_license($key = '')
131 {
132 $default = array(
133 'license_key' => '',
134 'error' => '',
135 'valid_until' => '',
136 'last_check' => 0,
137 'name' => '',
138 'meta' => array()
139 );
140
141 $options = get_option('wf_licensing_' . $this->prefix, array());
142 $options = array_merge($default, $options);
143
144 if (!empty($key)) {
145 return $options[$key];
146 } else {
147 return $options;
148 }
149 } // get_license
150
151
152 function get_license_formatted($key = '')
153 {
154 $license = $this->get_license();
155 $out = array(
156 'name' => '',
157 'name_long' => '',
158 'valid_until' => '',
159 'expires' => '',
160 'license_key' => '',
161 'license_key_hidden' => '',
162 'recurring' => false,
163 'keyless' => false,
164 );
165
166 if (!$this->is_active()) {
167 return $out;
168 }
169 $license['valid_until'] = $license['valid_until'];
170
171 $out['name'] = $license['name'];
172 $out['name_long'] = $license['name'];
173 if ($license['meta']) {
174 $tmp = '';
175 foreach ($license['meta'] as $meta => $meta_value) {
176
177 if ($meta[0] == '_' || filter_var($meta_value, FILTER_VALIDATE_BOOLEAN) != true) {
178 continue;
179 }
180 $meta = str_replace('_', ' ', $meta);
181 $meta = ucwords($meta);
182 $meta = str_ireplace('wpr ', 'WPR ', $meta);
183 $tmp .= $meta . ', ';
184 }
185 $tmp = trim($tmp, ', ');
186 if ($tmp) {
187 $out['name_long'] .= ' with ' . $tmp;
188 }
189 }
190
191 if ($license['valid_until'] == $this->valid_forever) {
192 $out['valid_until'] = 'forever';
193 $out['recurring'] = false;
194 } else {
195 $out['valid_until'] = 'until ' . date(get_option('date_format'), strtotime($license['valid_until']));
196 $out['recurring'] = true;
197 }
198
199 if (date('Y-m-d') == $license['valid_until']) {
200 $out['expires'] = 'today';
201 } elseif (date('Y-m-d', time() + 30 * DAY_IN_SECONDS) > $license['valid_until']) {
202 $tmp = (strtotime($license['valid_until'] . date(' G:i:s')) - time()) / DAY_IN_SECONDS;
203 $out['expires'] = 'in ' . round($tmp) . ' days';
204 } else {
205 $out['expires'] = 'in more than 30 days';
206 }
207
208 if (empty($license['license_key']) || $license['license_key'] == 'keyless') {
209 $out['keyless'] = true;
210 } else {
211 $out['keyless'] = false;
212 $out['license_key'] = $license['license_key'];
213 $tmp = strlen($license['license_key']);
214 $dash = false;
215 $new = '';
216 for ($i = $tmp - 1; $i >= 0; $i--) {
217 if ($dash == false || $out['license_key'][$i] == '-') {
218 $new = $out['license_key'][$i] . $new;
219 } else {
220 $new = '*' . $new;
221 }
222 if ($out['license_key'][$i] == '-') {
223 $dash = true;
224 }
225 }
226 $out['license_key_hidden'] = $new;
227 }
228
229 $out = apply_filters('wf_licensing_license_formatted_' . $this->prefix, $out);
230
231 if (!empty($key)) {
232 return $out[$key];
233 } else {
234 return $out;
235 }
236 } // get_license_formatted
237
238
239 /**
240 * Updates license details in the database.
241 *
242 * @param string $data License data to save; or empty to delete license
243 *
244 * @return bool
245 */
246 function update_license($data = false)
247 {
248 if (false === $data) {
249 $tmp = delete_option('wf_licensing_' . $this->prefix);
250 } else {
251 $tmp = update_option('wf_licensing_' . $this->prefix, $data);
252 }
253
254 return $tmp;
255 } // update_license
256
257
258 /**
259 * Check if license is valid
260 *
261 * @param string $feature If set it checks for a specific feature.
262 * @param bool $force_check Forces license recheck on server instead of just cached values.
263 *
264 * @return boolean
265 */
266 function is_active($feature = '', $force_check = false)
267 {
268 $last_check = $this->get_license('last_check');
269 if ($force_check || ($last_check && ($last_check + HOUR_IN_SECONDS * 8) < time())) {
270 $this->log('auto recheck license');
271 $this->validate();
272 }
273
274 $license = $this->get_license();
275
276 if (
277 !empty($license['license_key']) && !empty($license['name']) &&
278 !empty($license['valid_until']) && $license['valid_until'] >= date('Y-m-d')
279 ) {
280 if (!empty($feature)) {
281 if (!empty($license['meta'][$feature]) && filter_var($license['meta'][$feature], FILTER_VALIDATE_BOOLEAN) == true) {
282 return true;
283 } else {
284 return false;
285 }
286 } else {
287 return true;
288 }
289 } else {
290 return false;
291 }
292 } // is_active
293
294
295 /**
296 * Hook to plugin activation action.
297 * If there's a license key, try to activate & write response.
298 *
299 * @return void
300 */
301 function activate_plugin()
302 {
303 $license = $this->get_license();
304 if ($this->is_active() || empty($license['license_key'])) {
305 return false;
306 }
307
308 $tmp = $this->validate();
309 if ($tmp) {
310 $this->log('activating plugin, license activated');
311 return true;
312 } else {
313 $this->log('activating plugin, unable to activate license');
314 return false;
315 }
316 } // activate_plugin
317
318
319 /**
320 * Hook to plugin deactivation action.
321 * If there's a license key, try to deactivate & write response.
322 *
323 * @return void
324 */
325 function deactivate_plugin()
326 {
327 if (!$this->is_active()) {
328 return false;
329 }
330
331 $license = $this->get_license();
332 $result = $this->query_licensing_server('deactivate_license');
333
334 if (is_wp_error($result) || !is_array($result) || !isset($result['success']) || $result['success'] == false) {
335 $this->log('unable to deactivate license');
336
337 return false;
338 } else {
339 $license['error'] = '';
340 $license['name'] = '';
341 $license['valid_until'] = '';
342 $license['meta'] = '';
343 $license['last_check'] = 0;
344 $this->update_license($license);
345 $this->log('license deactivated');
346
347 return true;
348 }
349 } // deactivate_plugin
350
351
352 /**
353 * Use when uninstalling (deleting) the plugin to clean up.
354 *
355 * @param string $prefix Same prefix as used when initialising the class.
356 * @return bool
357 */
358 static function uninstall_plugin($prefix)
359 {
360 $tmp = delete_option('wf_licensing_' . $prefix);
361
362 return $tmp;
363 } // uninstall_plugin
364
365
366 /**
367 * Deletes license locally and send deactivate ping to licensing server
368 *
369 * @return void
370 */
371 function deactivate() {
372 $result = $this->query_licensing_server('deactivate_license', array());
373 $this->update_license(false);
374
375 return $result;
376 } // deactivate
377
378
379 /**
380 * Validate license key on server and save response.
381 *
382 * @param string $license_key License key, or leave empty to pull from saved.
383 *
384 * @return void
385 */
386 function validate($license_key = '')
387 {
388 $license = $this->get_license();
389 if (empty($license_key)) {
390 $license_key = $license['license_key'];
391 }
392
393 $out = array(
394 'license_key' => $license_key,
395 'error' => '',
396 'name' => '',
397 'last_check' => 0,
398 'valid_until' => '',
399 'meta' => array()
400 );
401
402 $result = $this->query_licensing_server('validate_license', array('license_key' => $license_key));
403
404 if (is_wp_error($result)) {
405 $out['error'] = 'Error querying licensing server. ' . $result->get_error_message() . ' Please try again in a few moments.';
406 $this->update_license($out);
407
408 return false;
409 } elseif (!is_array($result) || !isset($result['success'])) {
410 $out['error'] = 'Invalid response from licensing server. Please try again in a few moments.';
411 $this->update_license($out);
412
413 return false;
414 } elseif ($result['success'] == false) {
415 $out['error'] = $result['data'];
416 $this->update_license($out);
417
418 return true;
419 } else {
420 $out['error'] = $result['data']['error'];
421 $out['name'] = $result['data']['name'];
422 $out['valid_until'] = $result['data']['valid_until'];
423 $out['meta'] = $result['data']['meta'];
424 $out['last_check'] = time();
425 $this->update_license($out);
426
427 return true;
428 }
429 } // validate
430
431
432 function validate_ajax()
433 {
434 check_ajax_referer('wf_licensing_' . $this->prefix);
435
436 $license_key = trim($_REQUEST['license_key']);
437 if (empty($license_key)) {
438 $this->update_license(false);
439 do_action('wf_licensing_' . $this->prefix . '_validate_ajax', $license_key, false);
440
441 wp_send_json_success();
442 } else {
443 $result = $this->validate($license_key);
444 $license = $this->get_license();
445 do_action('wf_licensing_' . $this->prefix . '_validate_ajax', $license_key, $result);
446
447 if ($result == true) {
448 set_site_transient('update_plugins', null);
449 wp_send_json_success($result);
450 } else {
451 wp_send_json_error($license);
452 }
453 }
454 } // validate_ajax
455
456
457 function deactivate_ajax()
458 {
459 check_ajax_referer('wf_licensing_' . $this->prefix);
460
461 $old_license = $this->get_license();
462 $result = $this->deactivate();
463 do_action('wf_licensing_' . $this->prefix . '_deactivate_ajax', $old_license, $result);
464 wp_send_json_success($result);
465 } // deactivate_ajax
466
467
468 function save_ajax()
469 {
470 check_ajax_referer('wf_licensing_' . $this->prefix);
471
472 $out['license_key'] = trim($_POST['license_key']);
473
474 if ($_POST['success'] == 'true') {
475 $out['error'] = trim($_POST['data']['error']);
476 $out['name'] = trim($_POST['data']['name']);
477 $out['valid_until'] = trim($_POST['data']['valid_until']);
478 $out['meta'] = $_POST['data']['meta'];
479 } else {
480 $out['error'] = trim($_POST['data']);
481 $out['name'] = '';
482 $out['valid_until'] = '';
483 $out['meta'] = array();
484 }
485 $out['last_check'] = time();
486
487 $this->update_license($out);
488 do_action('wf_licensing_' . $this->prefix . '_save_ajax', $out);
489
490 wp_send_json_success();
491 } // save_ajax
492
493
494 /**
495 * Run license server query.
496 *
497 * @param string $action
498 * @param array $data
499 *
500 * @return string response|bool
501 */
502 function query_licensing_server($action, $data = array())
503 {
504 $license = $this->get_license();
505
506 $request_params = array('sslverify' => false, 'timeout' => 25, 'redirection' => 2);
507 $default_data = array(
508 'action' => '',
509 'license_key' => $license['license_key'],
510 'rand' => rand(1000, 9999),
511 'version' => $this->version,
512 'wp_version' => get_bloginfo('version'),
513 'site_url' => get_home_url(),
514 'site_title' => get_bloginfo('name'),
515 'meta' => array()
516 );
517
518 $request_data = array_merge($default_data, $data, array('action' => $action));
519 $request_data = apply_filters('wf_licensing_query_server_data', $request_data);
520 array_walk_recursive($request_data, function (&$val, $ind) {
521 $val = rawurlencode($val);
522 });
523
524 $this->log('query licensing server', $request_data);
525
526 $url = rtrim(add_query_arg($request_data, trailingslashit($this->licensing_servers[0] . $this->api_ver)), '&');
527 $response = wp_remote_get($url, $request_params);
528 $body = wp_remote_retrieve_body($response);
529 $result = @json_decode($body, true);
530
531 $this->log('licensing server response', $response);
532
533 if (is_wp_error($response) || empty($body) || !is_array($result) || !isset($result['success'])) {
534 if (is_wp_error($response)) {
535 return $response;
536 } else {
537 return new WP_Error(1, 'Invalid server response format.');
538 }
539 } else {
540 return $result;
541 }
542 } // query_licensing_server
543 } // WF_Licensing
544 } // if WF_Licensing
545