VaultPress - Version 2.0.1

Version Description

  • Release date: July 12, 2019

Bug Fixes

  • Security Scanner: ensure the Security Scanner can be triggered at all times.
Download this release

Release Info

Developer jeherve
Plugin Icon 128x128 VaultPress
Version 2.0.1
Comparing to
See all releases

Code changes from version 2.0 to 2.0.1

class-jetpack-logo.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Jetpack Logo for use on dashboard pages.
4
+ *
5
+ * @since 2.1.0
6
+ *
7
+ * @package VaultPress
8
+ */
9
+
10
+ use Automattic\Jetpack\Assets\Logo;
11
+
12
+ /**
13
+ * Jetpack Logo Class.
14
+ */
15
+ class Jetpack_Logo {
16
+ /**
17
+ * Constructor.
18
+ */
19
+ public function __construct() {
20
+ }
21
+
22
+ /**
23
+ * Display a Jetpack Logo.
24
+ */
25
+ public function output() {
26
+ $logo = new Logo();
27
+ return $logo->render();
28
+ }
29
+ }
class-vaultpress.php DELETED
@@ -1,2822 +0,0 @@
1
- <?php
2
- /**
3
- * Main VaultPress class.
4
- *
5
- * @package VaultPress
6
- */
7
-
8
- use Automattic\Jetpack\Assets\Logo;
9
-
10
- /**
11
- * Main VaultPress class.
12
- */
13
- class VaultPress {
14
- var $option_name = 'vaultpress';
15
- var $auto_register_option = 'vaultpress_auto_register';
16
- var $db_version = 4;
17
- var $plugin_version = VAULTPRESS__VERSION;
18
-
19
- function __construct() {
20
- register_activation_hook( __FILE__, array( $this, 'activate' ) );
21
- register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
22
-
23
- $this->options_blog_id = get_current_blog_id();
24
- $options = get_option( $this->option_name );
25
- if ( !is_array( $options ) )
26
- $options = array();
27
-
28
- $defaults = array(
29
- 'db_version' => 0,
30
- 'key' => '',
31
- 'secret' => '',
32
- 'connection' => false,
33
- 'service_ips_cidr' => false
34
- );
35
-
36
- $this->options = wp_parse_args( $options, $defaults );
37
- $this->reset_pings();
38
-
39
- $this->upgrade();
40
-
41
- $this->add_global_actions_and_filters();
42
-
43
- if ( is_admin() ) {
44
- $this->add_admin_actions_and_filters();
45
- }
46
-
47
- if ( $this->is_registered() ) {
48
- $do_not_backup = $this->get_option( 'do_not_backup' ) || $this->get_option( 'do_not_send_backup_pings' );
49
- if ( $do_not_backup )
50
- $this->add_vp_required_filters();
51
- else
52
- $this->add_listener_actions_and_filters();
53
- }
54
- }
55
-
56
- static function &init() {
57
- static $instance = false;
58
-
59
- if ( !$instance ) {
60
- $instance = new VaultPress();
61
- }
62
-
63
- return $instance;
64
- }
65
-
66
- static function register( $registration_key ) {
67
- $vp = self::init();
68
-
69
- $nonce = wp_create_nonce( 'vp_register_' . $registration_key );
70
- $args = array( 'registration_key' => $registration_key, 'nonce' => $nonce );
71
- $response = $vp->contact_service( 'register', $args );
72
-
73
- // Check for an error
74
- if ( ! empty( $response['faultCode'] ) )
75
- return new WP_Error( $response['faultCode'], $response['faultString'] );
76
-
77
- // Validate result
78
- if ( empty( $response['key'] ) || empty( $response['secret'] ) || empty( $response['nonce'] ) || $nonce != $response['nonce'] )
79
- return new WP_Error( 1, __( 'There was a problem trying to register your VaultPress subscription.' ) );
80
-
81
- // Store the result, force a connection test.
82
- $vp->update_option( 'key', $response['key'] );
83
- $vp->update_option( 'secret', $response['secret'] );
84
- $vp->check_connection( true );
85
-
86
- return true;
87
- }
88
-
89
- function activate( $network_wide ) {
90
- $type = $network_wide ? 'network' : 'single';
91
- $this->update_option( 'activated', $type );
92
-
93
- // force a connection check after an activation
94
- $this->clear_connection();
95
-
96
- if ( get_option( 'vaultpress_auto_connect' ) ) {
97
- $this->register_via_jetpack( true );
98
- }
99
- }
100
-
101
- function deactivate() {
102
- if ( $this->is_registered() )
103
- $this->contact_service( 'plugin_status', array( 'vp_plugin_status' => 'deactivated' ) );
104
- }
105
-
106
- function upgrade() {
107
- $current_db_version = $this->get_option( 'db_version' );
108
-
109
- if ( $current_db_version < 1 ) {
110
- $this->options['connection'] = get_option( 'vaultpress_connection' );
111
- $this->options['key'] = get_option( 'vaultpress_key' );
112
- $this->options['secret'] = get_option( 'vaultpress_secret' );
113
- $this->options['service_ips'] = get_option( 'vaultpress_service_ips' );
114
-
115
- // remove old options
116
- $old_options = array(
117
- 'vaultpress_connection',
118
- 'vaultpress_hostname',
119
- 'vaultpress_key',
120
- 'vaultpress_secret',
121
- 'vaultpress_service_ips',
122
- 'vaultpress_timeout',
123
- 'vp_allow_remote_execution',
124
- 'vp_debug_request_signing',
125
- 'vp_disable_firewall',
126
- );
127
-
128
- foreach ( $old_options as $option )
129
- delete_option( $option );
130
-
131
- $this->options['db_version'] = $this->db_version;
132
- $this->update_options();
133
- }
134
-
135
- if ( $current_db_version < 2 ) {
136
- $this->delete_option( 'timeout' );
137
- $this->delete_option( 'disable_firewall' );
138
- $this->update_option( 'db_version', $this->db_version );
139
- $this->clear_connection();
140
- }
141
-
142
- if ( $current_db_version < 3 ) {
143
- $this->update_firewall();
144
- $this->update_option( 'db_version', $this->db_version );
145
- $this->clear_connection();
146
- }
147
-
148
- if ( $current_db_version < 4 ) {
149
- $this->update_firewall();
150
- $this->update_option( 'db_version', $this->db_version );
151
- $this->clear_connection();
152
- }
153
- }
154
-
155
- function get_option( $key ) {
156
- if ( 'hostname' == $key ) {
157
- if ( defined( 'VAULTPRESS_HOSTNAME' ) )
158
- return VAULTPRESS_HOSTNAME;
159
- else
160
- return 'vaultpress.com';
161
- }
162
-
163
- if ( 'timeout' == $key ) {
164
- if ( defined( 'VAULTPRESS_TIMEOUT' ) )
165
- return VAULTPRESS_TIMEOUT;
166
- else
167
- return 60;
168
- }
169
-
170
- if ( 'disable_firewall' == $key ) {
171
- if ( defined( 'VAULTPRESS_DISABLE_FIREWALL' ) )
172
- return VAULTPRESS_DISABLE_FIREWALL;
173
- else
174
- return false;
175
- }
176
-
177
- if ( ( 'key' == $key || 'secret' == $key ) && empty( $this->options[$key] ) ) {
178
- return '';
179
- }
180
-
181
- // allow_forwarded_for can be overrided by config, or stored in or out of the vp option
182
- if ( 'allow_forwarded_for' === $key ) {
183
- if ( defined( 'ALLOW_FORWARDED_FOR' ) ) {
184
- return ALLOW_FORWARDED_FOR;
185
- }
186
-
187
- $standalone_option = get_option( 'vaultpress_allow_forwarded_for' );
188
- if ( ! empty( $standalone_option ) ) {
189
- return $standalone_option;
190
- }
191
- }
192
-
193
- if ( isset( $this->options[$key] ) )
194
- return $this->options[$key];
195
-
196
- return false;
197
- }
198
-
199
- function update_option( $key, $value ) {
200
- if ( 'allow_forwarded_for' === $key ) {
201
- update_option( 'vaultpress_allow_forwarded_for', $value );
202
-
203
- if ( isset( $this->options[ $key ] ) ) {
204
- unset( $this->options[ $key ] );
205
- $this->update_options();
206
- }
207
- return;
208
- }
209
-
210
- $this->options[$key] = $value;
211
- $this->update_options();
212
- }
213
-
214
- function delete_option( $key ) {
215
- if ( 'allow_forwarded_for' === $key ) {
216
- delete_option( 'vaultpress_allow_forwarded_for' );
217
- }
218
-
219
- unset( $this->options[$key] );
220
- $this->update_options();
221
- }
222
-
223
- function update_options() {
224
- // Avoid overwriting the VaultPress option if current blog_id has changed since reading it
225
- if ( get_current_blog_id() !== $this->options_blog_id ) {
226
- return;
227
- }
228
-
229
- update_option( $this->option_name, $this->options );
230
- }
231
-
232
- function admin_init() {
233
- if ( !current_user_can( 'manage_options' ) )
234
- return;
235
-
236
- load_plugin_textdomain( 'vaultpress', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
237
- }
238
-
239
- function admin_head() {
240
- if ( ! current_user_can( 'manage_options' ) ) {
241
- return;
242
- }
243
-
244
- // Array of hooks where we want to hook our notices.
245
- $notice_hooks = array( 'user_admin_notices' );
246
-
247
- /*
248
- * In the VaultPress dashboard, move the notices.
249
- */
250
- $screen = get_current_screen();
251
- if (
252
- ! is_null( $screen )
253
- && in_array(
254
- $screen->id,
255
- array( 'jetpack_page_vaultpress', 'toplevel_page_vaultpress' ),
256
- true
257
- )
258
- ) {
259
- $notice_hooks[] = 'vaultpress_notices';
260
- } else {
261
- $notice_hooks[] = 'admin_notices';
262
- }
263
-
264
- if ( $activated = $this->get_option( 'activated' ) ) {
265
- if ( 'network' == $activated ) {
266
- add_action( 'network_admin_notices', array( $this, 'activated_notice' ) );
267
- } else {
268
- foreach ( $notice_hooks as $filter ) {
269
- add_action( $filter, array( $this, 'activated_notice' ) );
270
- }
271
- }
272
- }
273
-
274
- // ask the user to connect their site w/ VP
275
- if ( !$this->is_registered() ) {
276
- foreach ( $notice_hooks as $filter ) {
277
- add_action( $filter, array( $this, 'connect_notice' ) );
278
- }
279
-
280
- // if we have an error make sure to let the user know about it
281
- } else {
282
- $error_code = $this->get_option( 'connection_error_code' );
283
- if ( ! empty( $error_code ) ) {
284
- foreach ( $notice_hooks as $filter ) {
285
- add_action( $filter, array( $this, 'error_notice' ) );
286
- }
287
- }
288
- }
289
- }
290
-
291
- function admin_menu() {
292
- // if Jetpack is loaded then we need to wait for that menu to be added
293
- if ( class_exists( 'Jetpack' ) )
294
- add_action( 'jetpack_admin_menu', array( $this, 'load_menu' ) );
295
- else
296
- $this->load_menu();
297
- }
298
-
299
- function load_menu() {
300
- if ( class_exists( 'Jetpack' ) ) {
301
- $hook = add_submenu_page( 'jetpack', 'VaultPress', 'VaultPress', 'manage_options', 'vaultpress', array( $this, 'ui' ) );
302
- } else {
303
- $hook = add_menu_page( 'VaultPress', 'VaultPress', 'manage_options', 'vaultpress', array( $this, 'ui' ), 'div' );
304
- }
305
-
306
- add_action( "load-$hook", array( $this, 'ui_load' ) );
307
- add_action( 'admin_print_styles', array( $this, 'styles' ) );
308
- }
309
-
310
- function styles() {
311
- if ( !current_user_can( 'manage_options' ) || !is_admin() )
312
- return;
313
-
314
- wp_enqueue_style( 'vaultpress-nav', plugins_url( '/nav-styles.css', __FILE__ ), false, date( 'Ymd' ) );
315
-
316
- if ( isset( $_GET['page'] ) && 'vaultpress' == $_GET['page'] )
317
- wp_enqueue_style( 'vaultpress', plugins_url( '/styles.css', __FILE__ ), false, date( 'Ymd' ) );
318
- }
319
-
320
- // display a security threat notice if one exists
321
- function toolbar( $wp_admin_bar ) {
322
- global $wp_version;
323
-
324
- // these new toolbar functions were introduced in 3.3
325
- // http://codex.wordpress.org/Function_Reference/add_node
326
- if ( version_compare( $wp_version, '3.3', '<') )
327
- return;
328
-
329
- if ( !current_user_can( 'manage_options' ) )
330
- return;
331
-
332
- $messages = $this->get_messages();
333
- if ( !empty( $messages['security_notice_count'] ) ) {
334
- $count = (int)$messages['security_notice_count'];
335
- if ( $count > 0 ) {
336
- $count = number_format( $count, 0 );
337
- $wp_admin_bar->add_node( array(
338
- 'id' => 'vp-notice',
339
- 'title' => '<span class="ab-icon"></span>' .
340
- sprintf( _n( '%s Security Threat', '%s Security Threats', $count , 'vaultpress'), $count ),
341
- 'parent' => 'top-secondary',
342
- 'href' => sprintf( 'https://dashboard.vaultpress.com/%d/security/', $messages['site_id'] ),
343
- 'meta' => array(
344
- 'title' => __( 'Visit VaultPress Security' , 'vaultpress'),
345
- 'onclick' => 'window.open( this.href ); return false;',
346
- 'class' => 'error'
347
- ),
348
- ) );
349
- }
350
- }
351
- }
352
-
353
- // get any messages from the VP servers
354
- function get_messages( $force_reload = false ) {
355
- $last_contact = $this->get_option( 'messages_last_contact' );
356
-
357
- // only run the messages check every 30 minutes
358
- if ( ( time() - (int)$last_contact ) > 1800 || $force_reload ) {
359
- $messages = base64_decode( $this->contact_service( 'messages', array() ) );
360
- $messages = unserialize( $messages );
361
- $this->update_option( 'messages_last_contact', time() );
362
- $this->update_option( 'messages', $messages );
363
- } else {
364
- $messages = $this->get_option( 'messages' );
365
- }
366
-
367
- return $messages;
368
- }
369
-
370
- function server_url() {
371
- if ( !isset( $this->_server_url ) ) {
372
- $scheme = is_ssl() ? 'https' : 'http';
373
- $this->_server_url = sprintf( '%s://%s/', $scheme, $this->get_option( 'hostname' ) );
374
- }
375
-
376
- return $this->_server_url;
377
- }
378
-
379
- // show message if plugin is activated but not connected to VaultPress
380
- function connect_notice() {
381
- if ( isset( $_GET['page'] ) && 'vaultpress' == $_GET['page'] )
382
- return;
383
-
384
- $message = sprintf(
385
- __( 'You must enter your registration key before VaultPress can back up and secure your site. <a href="%1$s">Register&nbsp;VaultPress</a>', 'vaultpress' ),
386
- admin_url( 'admin.php?page=vaultpress' )
387
- );
388
- $this->ui_message( $message, 'notice', __( 'VaultPress needs your attention!', 'vaultpress' ) );
389
- }
390
-
391
- // show message after activation
392
- function activated_notice() {
393
- if ( 'network' == $this->get_option( 'activated' ) ) {
394
- $message = sprintf(
395
- __( 'Each site will need to be registered with VaultPress separately. You can purchase new keys from your <a href="%1$s">VaultPress&nbsp;Dashboard</a>.', 'vaultpress' ),
396
- 'https://dashboard.vaultpress.com/'
397
- );
398
- $this->ui_message( $message, 'activated', __( 'VaultPress has been activated across your network!', 'vaultpress' ) );
399
-
400
- // key and secret already exist in db
401
- } elseif ( $this->is_registered() ) {
402
- if ( $this->check_connection() ) {
403
- }
404
- }
405
-
406
- $this->delete_option( 'activated' );
407
- }
408
-
409
- function error_notice() {
410
- $error_message = $this->get_option( 'connection_error_message' );
411
-
412
- // link to the VaultPress page if we're not already there
413
- if ( !isset( $_GET['page'] ) || 'vaultpress' != $_GET['page'] ) {
414
- $error_message .= ' ' . sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=vaultpress' ), __( 'Visit&nbsp;the&nbsp;VaultPress&nbsp;page' , 'vaultpress') );
415
- }
416
-
417
- $screen = get_current_screen();
418
- if ( !in_array( $screen->id, array( 'about', 'about-user', 'about-network' ) ) && !empty( $error_message ) ) {
419
- $this->ui_message( $error_message, 'error' );
420
- }
421
- }
422
-
423
- /**
424
- * Adds the main wrappers and the header, and defers controls to ui_render to decide which view to render.
425
- */
426
- function ui() {
427
- $ui_state = $this->ui_render();
428
- ?>
429
- <div id="jp-plugin-container">
430
- <?php $this->ui_masthead( $ui_state[ 'dashboard_link' ] ); ?>
431
- <div class="vp-wrap">
432
- <?php
433
- /**
434
- * Allow the display of custom notices.
435
- *
436
- * @since 2.0.0
437
- */
438
- do_action( 'vaultpress_notices' );
439
- ?>
440
- <?php echo $ui_state[ 'ui' ]; // This content is sanitized when it's produced. ?>
441
- </div>
442
- <?php $this->ui_footer(); ?>
443
- </div>
444
- <?php
445
- }
446
-
447
- /**
448
- * Decides which UI view to render and executes it.
449
- *
450
- * @return array $args {
451
- * An array of options to render the dashboard.
452
- *
453
- * @type string $ui Dashboard markup.
454
- * @type string $dashboard_link Whether to show the link to the VaultPress dashboard.
455
- * }
456
- */
457
- function ui_render() {
458
- ob_start();
459
-
460
- if ( $this->is_localhost() ) {
461
- $this->update_option( 'connection', time() );
462
- $this->update_option( 'connection_error_code', 'error_localhost' );
463
- $this->update_option( 'connection_error_message', 'Hostnames such as localhost or 127.0.0.1 can not be reached by vaultpress.com and will not work with the service. Sites must be publicly accessible in order to work with VaultPress.' );
464
- $this->error_notice();
465
- return array( 'ui' => ob_get_clean(), 'dashboard_link' => false );
466
- }
467
-
468
- if ( ! empty( $_GET[ 'error' ] ) ) {
469
- $this->error_notice();
470
- $this->clear_connection();
471
- }
472
-
473
- if ( ! $this->is_registered() ) {
474
- $this->ui_register();
475
- return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
476
- }
477
-
478
- $status = $this->contact_service( 'status' );
479
- if ( ! $status ) {
480
- $error_code = $this->get_option( 'connection_error_code' );
481
- if ( 0 == $error_code ) {
482
- $this->ui_fatal_error();
483
- } else {
484
- $this->ui_register();
485
- }
486
- return array( 'ui' => ob_get_clean(), 'dashboard_link' => 0 != $error_code );
487
- }
488
-
489
- $ticker = $this->contact_service( 'ticker' );
490
- if ( is_array( $ticker ) && isset( $ticker[ 'faultCode' ] ) ) {
491
- $this->error_notice();
492
- $this->ui_register();
493
- return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
494
- }
495
-
496
- $this->ui_main();
497
- return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
498
- }
499
-
500
- function ui_load() {
501
- if ( ! current_user_can( 'manage_options' ) ) {
502
- return;
503
- }
504
-
505
- if ( isset( $_POST['action'] ) && 'delete-vp-settings' == $_POST['action'] ) {
506
- check_admin_referer( 'delete_vp_settings' );
507
-
508
- $ai_ping_queue_size = $this->ai_ping_queue_size();
509
- if ( ! empty( $ai_ping_queue_size->option_count ) && $ai_ping_queue_size->option_count > 1 ) {
510
- $this->ai_ping_queue_delete();
511
- }
512
-
513
- delete_option( $this->option_name );
514
- delete_option( 'vaultpress_service_ips_external_cidr' );
515
- delete_option( '_vp_signatures' );
516
- delete_option( '_vp_config_option_name_ignore' );
517
- delete_option( '_vp_config_post_meta_name_ignore' );
518
- delete_option( '_vp_config_should_ignore_files' );
519
- delete_option( '_vp_current_scan' );
520
- delete_option( 'vaultpress_auto_register' );
521
-
522
- wp_redirect( admin_url( 'admin.php?page=vaultpress&delete-vp-settings=1' ) );
523
- exit();
524
- }
525
-
526
- // run code that might be updating the registration key
527
- if ( isset( $_POST['action'] ) && 'register' == $_POST['action'] ) {
528
- check_admin_referer( 'vaultpress_register' );
529
-
530
- // reset the connection info so messages don't cross
531
- $this->clear_connection();
532
-
533
- // if registering via Jetpack, get a key...
534
- if ( isset( $_POST['key_source'] ) && 'jetpack' === $_POST['key_source'] ) {
535
- $registration_key = $this->get_key_via_jetpack();
536
- if ( is_wp_error( $registration_key ) ) {
537
- $this->update_option( 'connection_error_code', -2 );
538
- $this->update_option(
539
- 'connection_error_message',
540
- sprintf( __('<strong>Failed to register VaultPress via Jetpack</strong>: %s. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ),
541
- esc_html( $registration_key->get_error_message() ), 'http://vaultpress.com/contact/' )
542
- );
543
- wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
544
- exit();
545
- }
546
- } else {
547
- $registration_key = trim( $_POST[ 'registration_key' ] );
548
- }
549
-
550
- if ( empty( $registration_key ) ) {
551
- $this->update_option( 'connection_error_code', 1 );
552
- $this->update_option(
553
- 'connection_error_message',
554
- sprintf(
555
- __( '<strong>That\'s not a valid registration key.</strong> Head over to the <a href="%1$s" title="Sign in to your VaultPress Dashboard">VaultPress&nbsp;Dashboard</a> to find your key.', 'vaultpress' ),
556
- 'https://dashboard.vaultpress.com/'
557
- )
558
- );
559
- wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
560
- exit();
561
- }
562
-
563
- // try to register the plugin
564
- $nonce = wp_create_nonce( 'vp_register_' . $registration_key );
565
- $args = array( 'registration_key' => $registration_key, 'nonce' => $nonce );
566
- $response = $this->contact_service( 'register', $args );
567
-
568
- // we received an error from the VaultPress servers
569
- if ( !empty( $response['faultCode'] ) ) {
570
- $this->update_option( 'connection_error_code', $response['faultCode'] );
571
- $this->update_option( 'connection_error_message', $response['faultString'] );
572
- wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
573
- exit();
574
- }
575
-
576
- // make sure the returned data looks valid
577
- if ( empty( $response['key'] ) || empty( $response['secret'] ) || empty( $response['nonce'] ) || $nonce != $response['nonce'] ) {
578
- $this->update_option( 'connection_error_code', 1 );
579
- $this->update_option( 'connection_error_message', sprintf( __( 'There was a problem trying to register your subscription. Please try again. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
580
- wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
581
- exit();
582
- }
583
-
584
- // need to update these values in the db so the servers can try connecting to the plugin
585
- $this->update_option( 'key', $response['key'] );
586
- $this->update_option( 'secret', $response['secret'] );
587
- if ( $this->check_connection( true ) ) {
588
- wp_redirect( admin_url( 'admin.php?page=vaultpress' ) );
589
- exit();
590
- }
591
-
592
- // reset the key and secret
593
- $this->update_option( 'key', '' );
594
- $this->update_option( 'secret', '' );
595
- wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
596
- exit();
597
- }
598
- }
599
-
600
- function ui_register() {
601
- ?>
602
- <div class="vp-notice__wide">
603
- <div class="dops-card">
604
- <img src="<?php echo esc_url( plugins_url( 'images/security.svg', __FILE__ ) ); ?>" alt="VaultPress">
605
- <h2><?php _e( 'The VaultPress plugin requires a subscription.', 'vaultpress' ); ?></h2>
606
- <p><?php _e( 'Get realtime backups, automated security scanning, and support from WordPress&nbsp;experts.', 'vaultpress' ); ?></p>
607
- <a class="dops-button is-primary" href="https://vaultpress.com/plugin/?utm_source=plugin-unregistered&amp;utm_medium=view-plans-and-pricing&amp;utm_campaign=1.0-plugin" target="_blank" rel="noopener noreferrer"><?php _e( 'View plans and pricing', 'vaultpress' ); ?></a>
608
- </div>
609
- </div>
610
-
611
- <div class="jp-dash-section-header">
612
- <div class="jp-dash-section-header__label">
613
- <h2 class="jp-dash-section-header__name">
614
- <?php esc_html_e( 'Management', 'vaultpress' ); ?>
615
- </h2>
616
- </div>
617
- </div>
618
-
619
- <div class="vp-row">
620
- <div class="vp-col">
621
- <div class="dops-card dops-section-header is-compact">
622
- <?php esc_html_e( 'Registration key', 'vaultpress' ) ?>
623
- </div>
624
- <div class="dops-card">
625
- <form method="post" action="">
626
- <fieldset>
627
- <p>
628
- <?php esc_html_e( 'Paste your registration key&nbsp;below:', 'vaultpress' ); ?>
629
- </p>
630
- <p>
631
- <textarea class="dops-textarea" placeholder="<?php esc_attr_e( __( 'Enter your key here...', 'vaultpress' ) ); ?>" name="registration_key"></textarea>
632
- </p>
633
- <button class="dops-button is-compact"><?php _e( 'Register ', 'vaultpress' ); ?></button>
634
- <input type="hidden" name="action" value="register" />
635
- <?php wp_nonce_field( 'vaultpress_register' ); ?>
636
- </fieldset>
637
- </form>
638
- </div>
639
- </div>
640
- <div class="vp-col">
641
- <?php $this->ui_delete_vp_settings_button(); ?>
642
- </div>
643
- </div>
644
- <?php
645
- }
646
-
647
- /**
648
- * Renders the top header.
649
- *
650
- * @param bool $show_nav Whether to show navigation.
651
- */
652
- function ui_masthead( $show_nav = true ) {
653
- ?>
654
- <div class="jp-masthead">
655
- <div class="jp-masthead__inside-container">
656
- <div class="jp-masthead__logo-container">
657
- <a class="jp-masthead__logo-link" href="https://vaultpress.com">
658
- <img src="<?php echo esc_url( plugins_url( 'images/vaultpress.svg', __FILE__ ) ); ?>" alt="VaultPress">
659
- </a>
660
- </div>
661
- <?php if ( $show_nav ) : ?>
662
- <div class="jp-masthead__nav">
663
- <div class="dops-button-group">
664
- <a href="https://dashboard.vaultpress.com" class="dops-button is-compact" target="_blank" rel="noopener noreferrer">
665
- <?php _e( 'Visit Dashboard', 'vaultpress' ); ?>
666
- </a>
667
- </div>
668
- </div>
669
- <?php endif; ?>
670
- </div>
671
- </div>
672
- <?php
673
- }
674
-
675
- /**
676
- * Renders the footer.
677
- */
678
- function ui_footer() {
679
- ?>
680
- <div class="jp-footer">
681
- <div class="jp-footer__a8c-attr-container">
682
- <svg role="img" class="jp-footer__a8c-attr" x="0" y="0" viewBox="0 0 935 38.2" enable-background="new 0 0 935 38.2" aria-labelledby="a8c-svg-title"><title id="a8c-svg-title">An Automattic Airline</title>
683
- <path d="M317.1 38.2c-12.6 0-20.7-9.1-20.7-18.5v-1.2c0-9.6 8.2-18.5 20.7-18.5 12.6 0 20.8 8.9 20.8 18.5v1.2C337.9 29.1 329.7 38.2 317.1 38.2zM331.2 18.6c0-6.9-5-13-14.1-13s-14 6.1-14 13v0.9c0 6.9 5 13.1 14 13.1s14.1-6.2 14.1-13.1V18.6zM175 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7L157 1.3h5.5L182 36.8H175zM159.7 8.2L152 23.1h15.7L159.7 8.2zM212.4 38.2c-12.7 0-18.7-6.9-18.7-16.2V1.3h6.6v20.9c0 6.6 4.3 10.5 12.5 10.5 8.4 0 11.9-3.9 11.9-10.5V1.3h6.7V22C231.4 30.8 225.8 38.2 212.4 38.2zM268.6 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H268.6zM397.3 36.8V8.7l-1.8 3.1 -14.9 25h-3.3l-14.7-25 -1.8-3.1v28.1h-6.5V1.3h9.2l14 24.4 1.7 3 1.7-3 13.9-24.4h9.1v35.5H397.3zM454.4 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7l19.2-35.5h5.5l19.5 35.5H454.4zM439.1 8.2l-7.7 14.9h15.7L439.1 8.2zM488.4 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H488.4zM537.3 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H537.3zM569.3 36.8V4.6c2.7 0 3.7-1.4 3.7-3.4h2.8v35.5L569.3 36.8 569.3 36.8zM628 11.3c-3.2-2.9-7.9-5.7-14.2-5.7 -9.5 0-14.8 6.5-14.8 13.3v0.7c0 6.7 5.4 13 15.3 13 5.9 0 10.8-2.8 13.9-5.7l4 4.2c-3.9 3.8-10.5 7.1-18.3 7.1 -13.4 0-21.6-8.7-21.6-18.3v-1.2c0-9.6 8.9-18.7 21.9-18.7 7.5 0 14.3 3.1 18 7.1L628 11.3zM321.5 12.4c1.2 0.8 1.5 2.4 0.8 3.6l-6.1 9.4c-0.8 1.2-2.4 1.6-3.6 0.8l0 0c-1.2-0.8-1.5-2.4-0.8-3.6l6.1-9.4C318.7 11.9 320.3 11.6 321.5 12.4L321.5 12.4z"></path>
684
- <path d="M37.5 36.7l-4.7-8.9H11.7l-4.6 8.9H0L19.4 0.8H25l19.7 35.9H37.5zM22 7.8l-7.8 15.1h15.9L22 7.8zM82.8 36.7l-23.3-24 -2.3-2.5v26.6h-6.7v-36H57l22.6 24 2.3 2.6V0.8h6.7v35.9H82.8z"></path>
685
- <path d="M719.9 37l-4.8-8.9H694l-4.6 8.9h-7.1l19.5-36h5.6l19.8 36H719.9zM704.4 8l-7.8 15.1h15.9L704.4 8zM733 37V1h6.8v36H733zM781 37c-1.8 0-2.6-2.5-2.9-5.8l-0.2-3.7c-0.2-3.6-1.7-5.1-8.4-5.1h-12.8V37H750V1h19.6c10.8 0 15.7 4.3 15.7 9.9 0 3.9-2 7.7-9 9 7 0.5 8.5 3.7 8.6 7.9l0.1 3c0.1 2.5 0.5 4.3 2.2 6.1V37H781zM778.5 11.8c0-2.6-2.1-5.1-7.9-5.1h-13.8v10.8h14.4c5 0 7.3-2.4 7.3-5.2V11.8zM794.8 37V1h6.8v30.4h28.2V37H794.8zM836.7 37V1h6.8v36H836.7zM886.2 37l-23.4-24.1 -2.3-2.5V37h-6.8V1h6.5l22.7 24.1 2.3 2.6V1h6.8v36H886.2zM902.3 37V1H935v5.6h-26v9.2h20v5.5h-20v10.1h26V37H902.3z"></path>
686
- </svg>
687
- </div>
688
- <ul class="jp-footer__links">
689
- <li class="jp-footer__link-item">
690
- <a href="https://vaultpress.com" class="jp-footer__link" title="<?php esc_attr_e( 'VaultPress version', 'vaultpress' ) ?>" target="_blank" rel="noopener noreferrer">
691
- <?php printf( 'VaultPress %s', $this->plugin_version ); ?>
692
- </a>
693
- </li>
694
- <li class="jp-footer__link-item">
695
- <a href="https://wordpress.com/tos/" class="jp-footer__link" title="<?php esc_attr_e( 'Terms of service', 'vaultpress' ) ?>" target="_blank" rel="noopener noreferrer">
696
- <?php esc_html_e( 'Terms', 'vaultpress' ); ?>
697
- </a>
698
- </li>
699
- </ul>
700
- <div class="jp-power">
701
- <a
702
- href="<?php echo class_exists( 'Jetpack_Admin_Page' ) ? esc_url( admin_url( 'admin.php?page=jetpack' ) ) : 'https://jetpack.com' ?>"
703
- class="jp-power__text-link"
704
- target="_blank"
705
- rel="noopener noreferrer"
706
- >
707
- <span class="jp-power__text"><?php esc_html_e( 'Powered by', 'vaultpress') ?></span> <?php echo $this->ui_logo(); ?>
708
- </a>
709
- </div>
710
- </div>
711
- <?php
712
- }
713
-
714
- function ui_main() {
715
- $response = base64_decode( $this->contact_service( 'plugin_ui' ) );
716
- echo $response;
717
- $this->ui_delete_vp_settings_button();
718
- }
719
-
720
- function ui_fatal_error() {
721
- $this->render_notice(
722
- sprintf(
723
- '<strong>' . __( 'We can\'t connect to %1$s.', 'vaultpress' ) . '</strong><br/>' .
724
- __( 'Please make sure that your website is accessible via the Internet. Please contact the VaultPress support if you still have issues.' ),
725
- esc_html( $this->get_option( 'hostname' ) )
726
- ),
727
- 'is-warning',
728
- array(
729
- 'label' => __( 'Contact support' ),
730
- 'url' => 'https://vaultpress.com/contact/',
731
- )
732
- );
733
- }
734
-
735
- function ui_message( $message, $type = 'notice', $heading = '' ) {
736
- $level = 'is-warning';
737
- if ( empty( $heading ) ) {
738
- switch ( $type ) {
739
- case 'error':
740
- $level = 'is-error';
741
- $heading = __( 'Oops... there seems to be a problem.', 'vaultpress' );
742
- break;
743
-
744
- case 'success':
745
- $level = 'is-success';
746
- $heading = __( 'Yay! Things look good.', 'vaultpress' );
747
- break;
748
-
749
- default:
750
- $heading = __( 'VaultPress needs your attention!', 'vaultpress' );
751
- break;
752
- }
753
- }
754
-
755
- $classes = in_array( get_current_screen()->parent_base, array( 'jetpack', 'vaultpress' ), true )
756
- ? ''
757
- : "notice notice-$type";
758
-
759
- $this->render_notice(
760
- "<strong>$heading</strong><br/>$message",
761
- $level,
762
- array(),
763
- $classes
764
- );
765
- }
766
-
767
- /**
768
- * Renders a notice. Can have
769
- *
770
- * @param string $content Notice main content.
771
- * @param string $level Can be is-info, is-warning, is-error. By default, it's is-info.
772
- * @param array $action {
773
- * Arguments to display a linked action button in the notice.
774
- *
775
- * @type string $label The action button label.
776
- * @type string $url The action button link.
777
- * }
778
- * @param string $classes This is added as a CSS class to the root node. Useful to pass WP core classes for notices.
779
- */
780
- function render_notice( $content, $level = 'is-info', $action = array(), $classes = '' ) {
781
- $allowed_html = array(
782
- 'a' => array( 'href' => true, 'target' => 'blank', 'rel' => 'noopener noreferrer' ),
783
- 'br' => true,
784
- 'strong' => true,
785
- );
786
- ?>
787
- <div class="dops-notice vp-notice <?php echo esc_attr( "$level $classes" ) ?>">
788
- <span class="dops-notice__icon-wrapper">
789
- <svg class="gridicon gridicons-info dops-notice__icon" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
790
- <path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" />
791
- </svg>
792
- </span>
793
- <span class="dops-notice__content">
794
- <span class="dops-notice__text"><?php echo wp_kses( $content, $allowed_html ) ?></span>
795
- </span>
796
- <?php if ( ! empty( $action ) ) : ?>
797
- <a class="dops-notice__action" href="<?php echo esc_attr( $action['url'] ) ?>" target="_blank" rel="noopener noreferrer">
798
- <span><?php echo esc_html( $action['label'] ) ?></span>
799
- </a>
800
- <?php endif; ?>
801
- </div>
802
- <?php
803
- }
804
-
805
- function ui_delete_vp_settings_button() {
806
- ?>
807
- <div class="dops-card dops-section-header is-compact">
808
- <?php _e( 'Settings reset', 'vaultpress' ); ?>
809
- </div>
810
- <?php
811
- if ( isset( $_GET['delete-vp-settings'] ) && 1 == (int) $_GET['delete-vp-settings'] ) {
812
- ?>
813
- <div class="dops-card">
814
- <p><?php _e( 'All VaultPress settings have been deleted.', 'vaultpress' ); ?></p>
815
- </div>
816
- <?php
817
- } else {
818
- ?>
819
- <div class="dops-card">
820
- <p><?php _e( 'Click this button to reset all VaultPress options in the database.', 'vaultpress' ); ?></p>
821
- <p><strong><?php esc_html_e( 'Warning: this process is irreversible.', 'vaultpress' ) ?></strong></p>
822
- <form
823
- onsubmit="return confirm( '<?php esc_html_e( 'Do you really want to reset all options?', 'vaultpress' ) ?>' );"
824
- method="post"
825
- action="">
826
- <button class="dops-button is-scary is-compact"><?php esc_html_e( 'Delete all settings', 'vaultpress' ); ?></button>
827
- <input type="hidden" name="action" value="delete-vp-settings"/>
828
- <?php wp_nonce_field( 'delete_vp_settings' ); ?>
829
- </form>
830
- </div>
831
- <?php
832
- }
833
- }
834
-
835
- /**
836
- * Render the Jetpack logo
837
- */
838
- function ui_logo() {
839
- $logo = new Logo();
840
- return $logo->render();
841
- }
842
-
843
- function get_config( $key ) {
844
- $val = get_option( $key );
845
- if ( $val )
846
- return $val;
847
- switch( $key ) {
848
- case '_vp_config_option_name_ignore':
849
- $val = $this->get_option_name_ignore( true );
850
- update_option( '_vp_config_option_name_ignore', $val );
851
- break;
852
- case '_vp_config_post_meta_name_ignore':
853
- $val = $this->get_post_meta_name_ignore( true );
854
- update_option( '_vp_config_post_meta_name_ignore', $val );
855
- break;
856
- case '_vp_config_should_ignore_files':
857
- $val = $this->get_should_ignore_files( true );
858
- update_option( '_vp_config_should_ignore_files', $val );
859
- break;
860
- }
861
- return $val;
862
- }
863
-
864
- // Option name patterns to ignore
865
- function get_option_name_ignore( $return_defaults = false ) {
866
- $defaults = array(
867
- 'vaultpress',
868
- 'cron',
869
- 'wpsupercache_gc_time',
870
- 'rewrite_rules',
871
- 'akismet_spam_count',
872
- '/_transient_/',
873
- '/^_vp_/',
874
- );
875
- if ( $return_defaults )
876
- return $defaults;
877
- $ignore_names = $this->get_config( '_vp_config_option_name_ignore' );
878
- return array_unique( array_merge( $defaults, $ignore_names ) );
879
- }
880
-
881
- // post meta name patterns to ignore
882
- function get_post_meta_name_ignore( $return_defaults = false ) {
883
- $defaults = array(
884
- 'pvc_views'
885
- );
886
- if ( $return_defaults )
887
- return $defaults;
888
- $ignore_names = $this->get_config( '_vp_config_post_meta_name_ignore' );
889
- return array_unique( array_merge( $defaults, $ignore_names ) );
890
- }
891
-
892
- // file name patterns to ignore
893
- function get_should_ignore_files( $return_defaults = false ) {
894
- $defaults = array();
895
- if ( $return_defaults )
896
- return $defaults;
897
- $ignore_names = (array) $this->get_config( '_vp_config_should_ignore_files' );
898
- return array_unique( array_merge( $defaults, $ignore_names ) );
899
- }
900
-
901
- ###
902
- ### Section: Backup Notification Hooks
903
- ###
904
-
905
- // Handle Handle Notifying VaultPress of Options Activity At this point the options table has already been modified
906
- //
907
- // Note: we handle deleted, instead of delete because VaultPress backs up options by name (which are unique,) that
908
- // means that we do not need to resolve an id like we would for, say, a post.
909
- function option_handler( $option_name ) {
910
- global $wpdb;
911
- // Step 1 -- exclusionary rules, don't send these options to vaultpress, because they
912
- // either change constantly and/or are inconsequential to the blog itself and/or they
913
- // are specific to the VaultPress plugin process and we want to avoid recursion
914
- $should_ping = true;
915
- $ignore_names = $this->get_option_name_ignore();
916
- foreach( (array)$ignore_names as $val ) {
917
- if ( $val{0} == '/' ) {
918
- if ( preg_match( $val, $option_name ) )
919
- $should_ping = false;
920
- } else {
921
- if ( $val == $option_name )
922
- $should_ping = false;
923
- }
924
- if ( !$should_ping )
925
- break;
926
- }
927
- if ( $should_ping )
928
- $this->add_ping( 'db', array( 'option' => $option_name ) );
929
-
930
- // Step 2 -- If WordPress is about to kick off a some "cron" action, we need to
931
- // flush vaultpress, because the "remote" cron threads done via http fetch will
932
- // be happening completely inside the window of this thread. That thread will
933
- // be expecting touched and accounted for tables
934
- if ( $option_name == '_transient_doing_cron' )
935
- $this->do_pings();
936
-
937
- return $option_name;
938
- }
939
-
940
- // Handle Notifying VaultPress of Comment Activity
941
- function comment_action_handler( $comment_id ) {
942
- if ( !is_array( $comment_id ) ) {
943
- if ( wp_get_comment_status( $comment_id ) != 'spam' )
944
- $this->add_ping( 'db', array( 'comment' => $comment_id ) );
945
- } else {
946
- foreach ( $comment_id as $id ) {
947
- if ( wp_get_comment_status( $comment_id ) != 'spam' )
948
- $this->add_ping( 'db', array( 'comment' => $id) );
949
- }
950
- }
951
- }
952
-
953
- // Handle Notifying VaultPress of Theme Switches
954
- function theme_action_handler( $theme ) {
955
- $this->add_ping( 'themes', array( 'theme' => get_option( 'stylesheet' ) ) );
956
- }
957
-
958
- // Handle Notifying VaultPress of Upload Activity
959
- function upload_handler( $file ) {
960
- $this->add_ping( 'uploads', array( 'upload' => str_replace( $this->resolve_upload_path(), '', $file['file'] ) ) );
961
- return $file;
962
- }
963
-
964
- // Handle Notifying VaultPress of Plugin Activation/Deactivation
965
- function plugin_action_handler( $plugin='' ) {
966
- $this->add_ping( 'plugins', array( 'name' => $plugin ) );
967
- }
968
-
969
- // Handle Notifying VaultPress of User Edits
970
- function userid_action_handler( $user_or_id ) {
971
- if ( is_object($user_or_id) )
972
- $userid = intval( $user_or_id->ID );
973
- else
974
- $userid = intval( $user_or_id );
975
- if ( !$userid )
976
- return;
977
- $this->add_ping( 'db', array( 'user' => $userid ) );
978
- }
979
-
980
- // Handle Notifying VaultPress of term changes
981
- function term_handler( $term_id, $tt_id=null ) {
982
- $this->add_ping( 'db', array( 'term' => $term_id ) );
983
- if ( $tt_id )
984
- $this->term_taxonomy_handler( $tt_id );
985
- }
986
-
987
- // Handle Notifying VaultPress of term_taxonomy changes
988
- function term_taxonomy_handler( $tt_id ) {
989
- $this->add_ping( 'db', array( 'term_taxonomy' => $tt_id ) );
990
- }
991
- // add(ed)_term_taxonomy handled via the created_term hook, the term_taxonomy_handler is called by the term_handler
992
-
993
- // Handle Notifying VaultPress of term_taxonomy changes
994
- function term_taxonomies_handler( $tt_ids ) {
995
- foreach( (array)$tt_ids as $tt_id ) {
996
- $this->term_taxonomy_handler( $tt_id );
997
- }
998
- }
999
-
1000
- // Handle Notifying VaultPress of term_relationship changes
1001
- function term_relationship_handler( $object_id, $term_id ) {
1002
- $this->add_ping( 'db', array( 'term_relationship' => array( 'object_id' => $object_id, 'term_taxonomy_id' => $term_id ) ) );
1003
- }
1004
-
1005
- // Handle Notifying VaultPress of term_relationship changes
1006
- function term_relationships_handler( $object_id, $term_ids ) {
1007
- foreach ( (array)$term_ids as $term_id ) {
1008
- $this->term_relationship_handler( $object_id, $term_id );
1009
- }
1010
- }
1011
-
1012
- // Handle Notifying VaultPress of term_relationship changes
1013
- function set_object_terms_handler( $object_id, $terms, $tt_ids ) {
1014
- $this->term_relationships_handler( $object_id, $tt_ids );
1015
- }
1016
-
1017
- // Handle Notifying VaultPress of UserMeta changes
1018
- function usermeta_action_handler( $umeta_id, $user_id, $meta_key, $meta_value='' ) {
1019
- $this->add_ping( 'db', array( 'usermeta' => $umeta_id ) );
1020
- }
1021
-
1022
- // Handle Notifying VaultPress of Post Changes
1023
- function post_action_handler($post_id) {
1024
- if ( current_filter() == 'delete_post' )
1025
- return $this->add_ping( 'db', array( 'post' => $post_id ), 'delete_post' );
1026
- return $this->add_ping( 'db', array( 'post' => $post_id ), 'edit_post' );
1027
- }
1028
-
1029
- // Handle Notifying VaultPress of Link Changes
1030
- function link_action_handler( $link_id ) {
1031
- $this->add_ping( 'db', array( 'link' => $link_id ) );
1032
- }
1033
-
1034
- // Handle Notifying VaultPress of Commentmeta Changes
1035
- function commentmeta_insert_handler( $meta_id, $comment_id=null ) {
1036
- if ( empty( $comment_id ) || wp_get_comment_status( $comment_id ) != 'spam' )
1037
- $this->add_ping( 'db', array( 'commentmeta' => $meta_id ) );
1038
- }
1039
-
1040
- function commentmeta_modification_handler( $meta_id, $object_id, $meta_key, $meta_value ) {
1041
- if ( !is_array( $meta_id ) )
1042
- return $this->add_ping( 'db', array( 'commentmeta' => $meta_id ) );
1043
- foreach ( $meta_id as $id ) {
1044
- $this->add_ping( 'db', array( 'commentmeta' => $id ) );
1045
- }
1046
- }
1047
-
1048
- // Handle Notifying VaultPress of PostMeta changes via newfangled metadata functions
1049
- function postmeta_insert_handler( $meta_id, $post_id, $meta_key, $meta_value='' ) {
1050
- if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1051
- return;
1052
-
1053
- $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1054
- }
1055
-
1056
- function postmeta_modification_handler( $meta_id, $object_id, $meta_key, $meta_value ) {
1057
- if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1058
- return;
1059
-
1060
- if ( !is_array( $meta_id ) )
1061
- return $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1062
- foreach ( $meta_id as $id ) {
1063
- $this->add_ping( 'db', array( 'postmeta' => $id ) );
1064
- }
1065
- }
1066
-
1067
- // Handle Notifying VaultPress of PostMeta changes via old school cherypicked hooks
1068
- function postmeta_action_handler( $meta_id, $post_id = null, $meta_key = null ) {
1069
- if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1070
- return;
1071
-
1072
- if ( !is_array($meta_id) )
1073
- return $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1074
- foreach ( $meta_id as $id )
1075
- $this->add_ping( 'db', array( 'postmeta' => $id ) );
1076
- }
1077
-
1078
- // WooCommerce notifications
1079
- function woocommerce_tax_rate_handler( $id ) {
1080
- $this->generic_change_handler( 'woocommerce_tax_rates', array( 'tax_rate_id' => $id ) );
1081
- $this->block_change_handler( 'woocommerce_tax_rate_locations', array( 'tax_rate_id' => $id ) );
1082
- }
1083
-
1084
- function woocommerce_order_item_handler( $id ) { $this->generic_change_handler( 'woocommerce_order_items', array( 'order_item_id' => $id ) ); }
1085
- function woocommerce_order_item_meta_handler( $id ) { $this->generic_change_handler( 'woocommerce_order_itemmeta', array( 'meta_id' => $id ) ); }
1086
- function woocommerce_attribute_handler( $id ) { $this->generic_change_handler( 'woocommerce_attribute_taxonomies', array( 'attribute_id' => $id ) ); }
1087
-
1088
- function generic_change_handler( $table, $key ) {
1089
- $this->add_ping( 'db', array( $table => $key ) );
1090
- }
1091
-
1092
- function block_change_handler( $table, $query ) {
1093
- $this->add_ping( 'db', array( "bulk~{$table}" => $query ) );
1094
- }
1095
-
1096
- function verify_table( $table ) {
1097
- global $wpdb;
1098
- $status = $wpdb->get_row( $wpdb->prepare( "SHOW TABLE STATUS WHERE Name = %s", $table ) );
1099
- if ( !$status || !$status->Update_time || !$status->Comment || $status->Engine != 'MyISAM' )
1100
- return true;
1101
- if ( preg_match( '/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})/', $status->Comment, $m ) )
1102
- return ( $m[1] == $status->Update_time );
1103
- return false;
1104
- }
1105
-
1106
- // Emulate $wpdb->last_table
1107
- function record_table( $table ) {
1108
- global $vaultpress_last_table;
1109
- $vaultpress_last_table = $table;
1110
- return $table;
1111
- }
1112
-
1113
- // Emulate $wpdb->last_table
1114
- function get_last_table() {
1115
- global $wpdb, $vaultpress_last_table;
1116
- if ( is_object( $wpdb ) && isset( $wpdb->last_table ) )
1117
- return $wpdb->last_table;
1118
- return $vaultpress_last_table;
1119
- }
1120
-
1121
- // Emulate hyperdb::is_write_query()
1122
- function is_write_query( $q ) {
1123
- $word = strtoupper( substr( trim( $q ), 0, 20 ) );
1124
- if ( 0 === strpos( $word, 'SELECT' ) )
1125
- return false;
1126
- if ( 0 === strpos( $word, 'SHOW' ) )
1127
- return false;
1128
- if ( 0 === strpos( $word, 'CHECKSUM' ) )
1129
- return false;
1130
- return true;
1131
- }
1132
-
1133
- // Emulate hyperdb::get_table_from_query()
1134
- function get_table_from_query( $q ) {
1135
- global $wpdb, $vaultpress_last_table;
1136
-
1137
- if ( is_object( $wpdb ) && method_exists( $wpdb, "get_table_from_query" ) )
1138
- return $wpdb->get_table_from_query( $q );
1139
-
1140
- // Remove characters that can legally trail the table name
1141
- $q = rtrim( $q, ';/-#' );
1142
- // allow ( select... ) union [...] style queries. Use the first queries table name.
1143
- $q = ltrim( $q, "\t (" );
1144
-
1145
- // Quickly match most common queries
1146
- if ( preg_match( '/^\s*(?:'
1147
- . 'SELECT.*?\s+FROM'
1148
- . '|INSERT(?:\s+IGNORE)?(?:\s+INTO)?'
1149
- . '|REPLACE(?:\s+INTO)?'
1150
- . '|UPDATE(?:\s+IGNORE)?'
1151
- . '|DELETE(?:\s+IGNORE)?(?:\s+FROM)?'
1152
- . ')\s+`?(\w+)`?/is', $q, $maybe) )
1153
- return $this->record_table($maybe[1] );
1154
-
1155
- // Refer to the previous query
1156
- if ( preg_match( '/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q ) )
1157
- return $this->get_last_table();
1158
-
1159
- // Big pattern for the rest of the table-related queries in MySQL 5.0
1160
- if ( preg_match( '/^\s*(?:'
1161
- . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
1162
- . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
1163
- . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
1164
- . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
1165
- . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?'
1166
- . '|DESCRIBE|DESC|EXPLAIN|HANDLER'
1167
- . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?'
1168
- . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|OPTIMIZE|REPAIR).*\s+TABLE'
1169
- . '|TRUNCATE(?:\s+TABLE)?'
1170
- . '|CREATE(?:\s+TEMPORARY)?\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?'
1171
- . '|ALTER(?:\s+IGNORE)?\s+TABLE'
1172
- . '|DROP\s+TABLE(?:\s+IF\s+EXISTS)?'
1173
- . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
1174
- . '|DROP\s+INDEX.*\s+ON'
1175
- . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
1176
- . '|(?:GRANT|REVOKE).*ON\s+TABLE'
1177
- . '|SHOW\s+(?:.*FROM|.*TABLE)'
1178
- . ')\s+`?(\w+)`?/is', $q, $maybe ) )
1179
- return $this->record_table( $maybe[1] );
1180
-
1181
- // All unmatched queries automatically fall to the global master
1182
- return $this->record_table( '' );
1183
- }
1184
-
1185
- function table_notify_columns( $table ) {
1186
- $want_cols = array(
1187
- // data
1188
- 'posts' => '`ID`',
1189
- 'users' => '`ID`',
1190
- 'links' => '`link_id`',
1191
- 'options' => '`option_id`,`option_name`',
1192
- 'comments' => '`comment_ID`',
1193
- // metadata
1194
- 'postmeta' => '`meta_id`',
1195
- 'commentmeta' => '`meta_id`',
1196
- 'usermeta' => '`umeta_id`',
1197
- // taxonomy
1198
- 'term_relationships' => '`object_id`,`term_taxonomy_id`',
1199
- 'term_taxonomy' => '`term_taxonomy_id`',
1200
- 'terms' => '`term_id`',
1201
- // plugin special cases
1202
- 'wpo_campaign' => '`id`', // WP-o-Matic
1203
- 'wpo_campaign_category' => '`id`', // WP-o-Matic
1204
- 'wpo_campaign_feed' => '`id`', // WP-o-Matic
1205
- 'wpo_campaign_post' => '`id`', // WP-o-Matic
1206
- 'wpo_campaign_word' => '`id`', // WP-o-Matic
1207
- 'wpo_log' => '`id`', // WP-o-Matic
1208
- );
1209
- if ( isset( $want_cols[$table] ) )
1210
- return $want_cols[$table];
1211
- return '*';
1212
- }
1213
-
1214
- /**
1215
- * Use an option ID to ensure a unique ping ID for the site.
1216
- *
1217
- * @return int|false The new ping number. False, if there was an error.
1218
- */
1219
- function ai_ping_next() {
1220
- global $wpdb;
1221
-
1222
- if ( ! $this->allow_ai_pings() ) {
1223
- return false;
1224
- }
1225
-
1226
- $name = "_vp_ai_ping";
1227
- $wpdb->query( $wpdb->prepare( "DELETE FROM `$wpdb->options` WHERE `option_name` = %s;", $name ) );
1228
- $success = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, '', 'no')", $name ) );
1229
- if ( ! $success ) {
1230
- return false;
1231
- }
1232
- return $wpdb->insert_id;
1233
- }
1234
-
1235
- function ai_ping_insert( $value ) {
1236
- if ( ! $this->allow_ai_pings() ) {
1237
- return false;
1238
- }
1239
-
1240
- $new_id = $this->ai_ping_next();
1241
-
1242
- if ( !$new_id )
1243
- return false;
1244
- add_option( '_vp_ai_ping_' . $new_id, $value, '', 'no' );
1245
- }
1246
-
1247
- function allow_ai_pings() {
1248
- static $allow_ai_pings = null;
1249
-
1250
- if ( null === $allow_ai_pings ) {
1251
- $queue_size = $this->ai_ping_queue_size();
1252
- $size_limit = 50 * 1024 * 1024;
1253
- $allow_ai_pings = ( $queue_size->option_count < 100 && $queue_size->option_size < $size_limit );
1254
- }
1255
-
1256
- return $allow_ai_pings;
1257
- }
1258
-
1259
- function ai_ping_queue_size() {
1260
- global $wpdb;
1261
- return $wpdb->get_row( "SELECT COUNT(`option_id`) `option_count`, SUM(LENGTH(`option_value`)) `option_size` FROM $wpdb->options WHERE `option_name` LIKE '\_vp\_ai\_ping\_%'" );
1262
- }
1263
-
1264
- function ai_ping_get( $num=1, $order='ASC' ) {
1265
- global $wpdb;
1266
- if ( strtolower($order) != 'desc' )
1267
- $order = 'ASC';
1268
- else
1269
- $order = 'DESC';
1270
- return $wpdb->get_results( $wpdb->prepare(
1271
- "SELECT * FROM $wpdb->options WHERE `option_name` LIKE '\_vp\_ai\_ping\_%%' ORDER BY `option_id` $order LIMIT %d",
1272
- min( 10, max( 1, (int)$num ) )
1273
- ) );
1274
- }
1275
-
1276
- function ai_ping_queue_delete() {
1277
- global $wpdb;
1278
-
1279
- return $wpdb->query( "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '\_vp\_ai\_ping%'" );
1280
- }
1281
-
1282
- function request_firewall_update( $external_services = false ) {
1283
- $args = array( 'timeout' => $this->get_option( 'timeout' ), 'sslverify' => true );
1284
- $hostname = $this->get_option( 'hostname' );
1285
- $path = $external_services ? 'service-ips-external' : 'service-ips';
1286
-
1287
- $data = false;
1288
- $https_error = null;
1289
- $retry = 2;
1290
- $protocol = 'https';
1291
- do {
1292
- $retry--;
1293
- $args['sslverify'] = 'https' == $protocol ? true : false;
1294
- $r = wp_remote_get( $url=sprintf( "%s://%s/%s?cidr_ranges=1", $protocol, $hostname, $path ), $args );
1295
- if ( 200 == wp_remote_retrieve_response_code( $r ) ) {
1296
- if ( 99 == $this->get_option( 'connection_error_code' ) )
1297
- $this->clear_connection();
1298
- $data = @unserialize( wp_remote_retrieve_body( $r ) );
1299
- break;
1300
- }
1301
- if ( 'https' == $protocol ) {
1302
- $https_error = $r;
1303
- $protocol = 'http';
1304
- }
1305
- usleep( 100 );
1306
- } while( $retry > 0 );
1307
-
1308
- if ( $https_error != null && ! empty( $data ) ) {
1309
- $r_code = wp_remote_retrieve_response_code( $https_error );
1310
- if ( 200 != $r_code ) {
1311
- $error_message = sprintf( 'Unexpected HTTP response code %s', $r_code );
1312
- if ( false === $r_code )
1313
- $error_message = 'Unable to find an HTTP transport that supports SSL verification';
1314
- elseif ( is_wp_error( $https_error ) )
1315
- $error_message = $https_error->get_error_message();
1316
-
1317
- $this->update_option( 'connection', time() );
1318
- $this->update_option( 'connection_error_code', 99 );
1319
- $this->update_option( 'connection_error_message', sprintf( __('Warning: The VaultPress plugin is using an insecure protocol because it cannot verify the identity of the VaultPress server. Please contact your hosting provider, and ask them to check that SSL certificate verification is correctly configured on this server. The request failed with the following error: "%s". If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), esc_html( $error_message ), 'http://vaultpress.com/contact/' ) );
1320
- }
1321
- }
1322
-
1323
- return $data;
1324
- }
1325
-
1326
- function update_firewall() {
1327
- $data = $this->request_firewall_update();
1328
- if ( $data ) {
1329
- $newval = array( 'updated' => time(), 'data' => $data );
1330
- $this->update_option( 'service_ips_cidr', $newval );
1331
- }
1332
-
1333
- $external_data = $this->request_firewall_update( true );
1334
- if ( $external_data ) {
1335
- $external_newval = array( 'updated' => time(), 'data' => $external_data );
1336
-
1337
- delete_option( 'vaultpress_service_ips_external_cidr' );
1338
- add_option( 'vaultpress_service_ips_external_cidr', $external_newval, '', 'no' );
1339
- }
1340
-
1341
- if ( !empty( $data ) && !empty( $external_data ) )
1342
- $data = array_merge( $data, $external_data );
1343
-
1344
- if ( $data ) {
1345
- return $data;
1346
- } else {
1347
- return null;
1348
- }
1349
- }
1350
-
1351
- // Update local cache of VP plan settings, based on a ping or connection test result
1352
- function update_plan_settings( $message ) {
1353
- if ( array_key_exists( 'do_backups', $message ) )
1354
- $this->update_option( 'do_not_backup', ( false === $message['do_backups'] ) || ( '0' === $message['do_backups'] ) );
1355
-
1356
- if ( array_key_exists( 'do_backup_pings', $message ) )
1357
- $this->update_option( 'do_not_send_backup_pings', ( false === $message['do_backup_pings'] ) || ( '0' === $message['do_backup_pings'] ) );
1358
- }
1359
-
1360
- function check_connection( $force_check = false ) {
1361
- $connection = $this->get_option( 'connection' );
1362
-
1363
- if ( !$force_check && !empty( $connection ) ) {
1364
- // already established a connection
1365
- if ( 'ok' == $connection )
1366
- return true;
1367
-
1368
- // only run the connection check every 5 minutes
1369
- if ( ( time() - (int)$connection ) < 300 )
1370
- return false;
1371
- }
1372
-
1373
- // if we're running a connection test we don't want to run it a second time
1374
- $connection_test = $this->get_option( 'connection_test' );
1375
- if ( ! empty( $connection_test ) )
1376
- return true;
1377
-
1378
- // force update firewall settings
1379
- $this->update_firewall();
1380
-
1381
- // Generate a random string for ping-backs to use for identification
1382
- $connection_test_key = wp_generate_password( 32, false );
1383
- $this->update_option( 'connection_test', $connection_test_key );
1384
-
1385
- // initial connection test to server
1386
- $this->delete_option( 'allow_forwarded_for' );
1387
- $host = ( ! empty( $_SERVER['HTTP_HOST'] ) ) ? $_SERVER['HTTP_HOST'] : parse_url( $this->site_url(), PHP_URL_HOST );
1388
- $connect = $this->contact_service( 'test', array( 'host' => $host, 'uri' => $_SERVER['REQUEST_URI'], 'ssl' => is_ssl() ) );
1389
-
1390
- // we can't see the servers at all
1391
- if ( !$connect ) {
1392
- $this->update_option( 'connection', time() );
1393
- $this->update_option( 'connection_error_code', 0 );
1394
- $this->update_option( 'connection_error_message', sprintf( __( 'Cannot connect to the VaultPress servers. Please check that your host allows connecting to external sites and try again. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
1395
-
1396
- $this->delete_option( 'connection_test' );
1397
- return false;
1398
- }
1399
-
1400
- // VaultPress gave us a meaningful error
1401
- if ( !empty( $connect['faultCode'] ) ) {
1402
- $this->update_option( 'connection', time() );
1403
- $this->update_option( 'connection_error_code', $connect['faultCode'] );
1404
- $this->update_option( 'connection_error_message', $connect['faultString'] );
1405
- $this->delete_option( 'connection_test' );
1406
- return false;
1407
- }
1408
-
1409
- $this->update_plan_settings( $connect );
1410
-
1411
- if ( !empty( $connect['signatures'] ) ) {
1412
- delete_option( '_vp_signatures' );
1413
- add_option( '_vp_signatures', maybe_unserialize( $connect['signatures'] ), '', 'no' );
1414
- }
1415
-
1416
- // test connection between the site and the servers
1417
- $connect = (string)$this->contact_service( 'test', array( 'type' => 'connect', 'test_key' => $connection_test_key ) );
1418
- if ( 'ok' != $connect ) {
1419
- if ( 'error' == $connect ) {
1420
- $this->update_option( 'connection_error_code', -1 );
1421
- $this->update_option( 'connection_error_message', sprintf( __( 'The VaultPress servers cannot connect to your site. Please check that your site is visible over the Internet and there are no firewall or load balancer settings on your server that might be blocking the communication. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
1422
- } elseif ( !empty( $connect['faultCode'] ) ) {
1423
- $this->update_option( 'connection_error_code', $connect['faultCode'] );
1424
- $this->update_option( 'connection_error_message', $connect['faultString'] );
1425
- }
1426
-
1427
- $this->update_option( 'connection', time() );
1428
- $this->delete_option( 'connection_test' );
1429
- return false;
1430
- }
1431
-
1432
- // successful connection established
1433
- $this->update_option( 'connection', 'ok' );
1434
- $this->delete_option( 'connection_error_code' );
1435
- $this->delete_option( 'connection_error_message' );
1436
- $this->delete_option( 'connection_test' );
1437
- return true;
1438
- }
1439
-
1440
- function get_login_tokens() {
1441
- // By default the login token is valid for 30 minutes.
1442
- $nonce_life = $this->get_option( 'nonce_life' ) ? $this->get_option( 'nonce_life' ) : 1800;
1443
- $salt = wp_salt( 'nonce' ) . md5( $this->get_option( 'secret' ) );
1444
- $nonce_life /= 2;
1445
-
1446
- return array(
1447
- 'previous' => substr( hash_hmac( 'md5', 'vp-login' . ceil( time() / $nonce_life - 1 ), $salt ), -12, 10 ),
1448
- 'current' => substr( hash_hmac( 'md5', 'vp-login' . ceil( time() / $nonce_life ), $salt ), -12, 10 ),
1449
- );
1450
- }
1451
- function add_js_token() {
1452
- $nonce = $this->get_login_tokens();
1453
- $token = $nonce['current'];
1454
-
1455
- // Uglyfies the JS code before sending it to the browser.
1456
- $whitelist = array( 'charAt', 'all', 'setAttribute', 'document', 'createElement', 'appendChild', 'input', 'hidden', 'type', 'name', 'value', 'getElementById', 'loginform', '_vp' );
1457
- shuffle( $whitelist );
1458
- $whitelist = array_flip( $whitelist );
1459
-
1460
- $set = array(
1461
- 0 => array( '+[]', 'e^e' ),
1462
- 1 => array( '+!![]', '2>>1', "e[{$whitelist['type']}].charCodeAt(3)>>6" ),
1463
- 2 => array( '(+!![])<<1', "e[{$whitelist['_vp']}].replace(/_/,'').length" ),
1464
- 3 => array( "(Math.log(2<<4)+[])[e[{$whitelist['charAt']}]](0)", "e[{$whitelist['_vp']}].length" ),
1465
- 4 => array( '(+!![])<<2', "e[{$whitelist['input']}].length^1", "e[{$whitelist['name']}].length" ),
1466
- 5 => array( '((1<<2)+1)', 'parseInt("f",0x10)/3' ),
1467
- 6 => array( '(7^1)', "e[{$whitelist['hidden']}].length" ),
1468
- 7 => array( '(3<<1)+1', "e[{$whitelist['hidden']}].length^1" ),
1469
- 8 => array( '(0x101>>5)', "e[{$whitelist['document']}].length" ),
1470
- 9 => array( '(0x7^4)*(3+[])', "e[{$whitelist['loginform']}].length", "(1<<e[{$whitelist['_vp']}].length)^1" ),
1471
- 'a' => array( "(![]+\"\")[e[{$whitelist['charAt']}]](1)", "e[{$whitelist['appendChild']}][e[{$whitelist['charAt']}]](0)", "e[{$whitelist['name']}][e[{$whitelist['charAt']}]](1)" ),
1472
- 'b' => array( "([]+{})[e[{$whitelist['charAt']}]](2)", "({}+[])[e[{$whitelist['charAt']}]](2)" ),
1473
- 'c' => array( "([]+{})[e[{$whitelist['charAt']}]](5)", "e[{$whitelist['createElement']}][e[{$whitelist['charAt']}]](0)" ),
1474
- 'd' => array( "([][0]+\"\")[e[{$whitelist['charAt']}]](2)", "([][0]+[])[e[{$whitelist['charAt']}]](2)" ),
1475
- 'e' => array( "(!![]+[])[e[{$whitelist['charAt']}]](3)", "(!![]+\"\")[e[{$whitelist['charAt']}]](3)" ),
1476
- 'f' => array( "(![]+[])[e[{$whitelist['charAt']}]](0)", "([]+![])[e[{$whitelist['charAt']}]](e^e)", "([]+![])[e[{$whitelist['charAt']}]](0)" ),
1477
- );
1478
-
1479
- $js_code = <<<JS
1480
- <script type="text/javascript">
1481
- /* <![CDATA[ */
1482
- (function(){
1483
- var i,e='%s'.split('|'),_=[%s],s=function(a,b,c){a[b]=c};
1484
- if(this[e[{$whitelist['document']}]][e[{$whitelist['all']}]]){
1485
- try {
1486
- i=this[e[{$whitelist['document']}]][e[{$whitelist['createElement']}]]('<'+e[{$whitelist['input']}]+' '+e[{$whitelist['name']}]+'='+(e[{$whitelist['_vp']}]+(!![]))+' />');
1487
- }catch(e){}
1488
- }
1489
- if(!i){
1490
- i=this[e[{$whitelist['document']}]][e[{$whitelist['createElement']}]](e[{$whitelist['input']}]);
1491
- s(i,e[{$whitelist['name']}],e[{$whitelist['_vp']}]+(!![]));
1492
- }
1493
- s(i,e[{$whitelist['type']}],e[{$whitelist['hidden']}]).
1494
- s(i,e[{$whitelist['value']}],(%s+""));
1495
- try {
1496
- var __=this[e[{$whitelist['document']}]][e[{$whitelist['getElementById']}]](e[{$whitelist['loginform']}]);
1497
- __[e[{$whitelist['appendChild']}]](i);
1498
- } catch(e){}
1499
- })();
1500
- /* ]]> */
1501
- </script>
1502
- JS;
1503
- $chars = array();
1504
- for ( $i = 0; $i < strlen( $token ); $i++ ) {
1505
- if ( isset( $set[$token{$i}] ) ) {
1506
- $k = array_rand( $set[$token{$i}], 1 );
1507
- $chars[] = $set[$token{$i}][$k];
1508
- } else {
1509
- $chars[] = $token{$i};
1510
- }
1511
- }
1512
- $random = array_unique( $chars );
1513
- shuffle( $random );
1514
- $random = array_flip( $random );
1515
-
1516
- foreach( $chars as $i => $v )
1517
- $chars[$i] = sprintf( '_[%d]', $random[$v] );
1518
-
1519
- $code = preg_replace(
1520
- "#[\n\r\t]#",
1521
- '',
1522
- sprintf( $js_code,
1523
- join( '|', array_keys( $whitelist ) ),
1524
- join( ',', array_keys( $random ) ),
1525
- join( '+"")+(', $chars )
1526
- )
1527
- );
1528
- echo $code;
1529
- }
1530
-
1531
- function authenticate( $user, $username, $password ) {
1532
- if ( is_wp_error( $user ) )
1533
- return $user;
1534
- if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST || defined( 'APP_REQUEST' ) && APP_REQUEST ) {
1535
- // Try to log in with the username and password.
1536
- }
1537
- $retval = $user;
1538
- if ( empty( $_POST['_vptrue'] ) || !in_array( $_POST['_vptrue'], $this->get_login_tokens(), true ) )
1539
- $retval = new WP_Error( 'invalid_token', __( 'Invalid token. Please try to log in again.' ) );
1540
-
1541
- return $retval;
1542
- }
1543
-
1544
- function parse_request( $wp ) {
1545
- if ( !isset( $_GET['vaultpress'] ) || $_GET['vaultpress'] !== 'true' )
1546
- return $wp;
1547
-
1548
- global $wpdb, $current_blog;
1549
-
1550
- // just in case we have any plugins that decided to spit some data out already...
1551
- @ob_end_clean();
1552
- // Headers to avoid search engines indexing "invalid api call signature" pages.
1553
- if ( !headers_sent() ) {
1554
- header( 'X-Robots-Tag: none' );
1555
- header( 'X-Robots-Tag: unavailable_after: 1 Oct 2012 00:00:00 PST', false );
1556
- }
1557
-
1558
- if ( isset( $_GET['ticker'] ) && function_exists( 'current_user_can' ) && current_user_can( 'manage_options' ) )
1559
- die( (string)$this->contact_service( 'ticker' ) );
1560
-
1561
- $_POST = array_map( 'stripslashes_deep', $_POST );
1562
-
1563
- global $wpdb, $bdb, $bfs;
1564
- define( 'VAULTPRESS_API', true );
1565
-
1566
- if ( !$this->validate_api_signature() ) {
1567
- global $__vp_validate_error;
1568
- die( 'invalid api call signature [' . base64_encode( serialize( $__vp_validate_error ) ) . ']' );
1569
- }
1570
-
1571
- if ( !empty( $_GET['ge'] ) ) {
1572
- // "ge" -- "GET encoding"
1573
- if ( '1' === $_GET['ge'] )
1574
- $_GET['action'] = base64_decode( $_GET['action'] );
1575
- if ( '2' === $_GET['ge'] )
1576
- $_GET['action'] = str_rot13( $_GET['action'] );
1577
- }
1578
-
1579
- if ( !empty( $_GET['pe'] ) ) {
1580
- // "pe" -- POST encoding
1581
- if ( '1' === $_GET['pe'] ) {
1582
- foreach( $_POST as $idx => $val ) {
1583
- if ( $idx === 'signature' )
1584
- continue;
1585
- $_POST[ base64_decode( $idx ) ] = base64_decode( $val );
1586
- unset( $_POST[$idx] );
1587
- }
1588
- }
1589
- if ( '2' === $_GET['pe'] ) {
1590
- foreach( $_POST as $idx => $val ) {
1591
- if ( $idx === 'signature' )
1592
- continue;
1593
- $_POST[ base64_decode( $idx ) ] = str_rot13( $val );
1594
- unset( $_POST[$idx] );
1595
- }
1596
- }
1597
- }
1598
-
1599
- if ( !isset( $bdb ) ) {
1600
- require_once( dirname( __FILE__ ) . '/class.vaultpress-database.php' );
1601
- require_once( dirname( __FILE__ ) . '/class.vaultpress-filesystem.php' );
1602
-
1603
- $bdb = new VaultPress_Database();
1604
- $bfs = new VaultPress_Filesystem();
1605
- }
1606
-
1607
- header( 'Content-Type: text/plain' );
1608
-
1609
- /*
1610
- * general:ping
1611
- *
1612
- * catchup:get
1613
- * catchup:delete
1614
- *
1615
- * db:tables
1616
- * db:explain
1617
- * db:cols
1618
- *
1619
- * plugins|themes|uploads|content|root:active
1620
- * plugins|themes|uploads|content|root:dir
1621
- * plugins|themes|uploads|content|root:ls
1622
- * plugins|themes|uploads|content|root:stat
1623
- * plugins|themes|uploads|content|root:get
1624
- * plugins|themes|uploads|content|root:checksum
1625
- *
1626
- * config:get
1627
- * config:set
1628
- *
1629
- */
1630
- if ( !isset( $_GET['action'] ) )
1631
- die();
1632
-
1633
- switch ( $_GET['action'] ) {
1634
- default:
1635
- die();
1636
- break;
1637
- case 'exec':
1638
- $code = $_POST['code'];
1639
- if ( !$code )
1640
- $this->response( "No Code Found" );
1641
- $syntax_check = @eval( 'return true;' . $code );
1642
- if ( !$syntax_check )
1643
- $this->response( "Code Failed Syntax Check" );
1644
- $this->response( eval( $code . ';' ) );
1645
- die();
1646
- break;
1647
- case 'catchup:get':
1648
- $this->response( $this->ai_ping_get( (int)$_POST['num'], (string)$_POST['order'] ) );
1649
- break;
1650
- case 'catchup:delete':
1651
- if ( isset( $_POST['pings'] ) ) {
1652
- foreach( unserialize( $_POST['pings'] ) as $ping ) {
1653
- if ( 0 === strpos( $ping, '_vp_ai_ping_' ) )
1654
- delete_option( $ping );
1655
- }
1656
- }
1657
- break;
1658
- case 'general:ping':
1659
- global $wp_version, $wp_db_version, $manifest_version;
1660
- @error_reporting(0);
1661
- $http_modules = array();
1662
- $httpd = null;
1663
- if ( function_exists( 'apache_get_modules' ) ) {
1664
- if ( isset( $_POST['apache_modules'] ) && $_POST['apache_modules'] == 1 )
1665
- $http_modules = apache_get_modules();
1666
- else
1667
- $http_modules = null;
1668
- if ( function_exists( 'apache_get_version' ) ) {
1669
- $version_pieces = explode( ' ', apache_get_version() );
1670
- $httpd = array_shift( $version_pieces );
1671
- }
1672
- }
1673
- if ( !$httpd && 0 === stripos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) ) {
1674
- $software_pieces = explode( ' ', $_SERVER['SERVER_SOFTWARE'] );
1675
- $httpd = array_shift( $software_pieces );
1676
- if ( isset( $_POST['apache_modules'] ) && $_POST['apache_modules'] == 1 )
1677
- $http_modules = 'unknown';
1678
- else
1679
- $http_modules = null;
1680
- }
1681
- if ( !$httpd && defined( 'IIS_SCRIPT' ) && IIS_SCRIPT ) {
1682
- $httpd = 'IIS';
1683
- }
1684
- if ( !$httpd && function_exists( 'nsapi_request_headers' ) ) {
1685
- $httpd = 'NSAPI';
1686
- }
1687
- if ( !$httpd )
1688
- $httpd = 'unknown';
1689
- $mvars = array();
1690
- if ( isset( $_POST['mysql_variables'] ) && $_POST['mysql_variables'] == 1 ) {
1691
- foreach ( $wpdb->get_results( "SHOW VARIABLES" ) as $row )
1692
- $mvars["$row->Variable_name"] = $row->Value;
1693
- }
1694
-
1695
- $this->update_plan_settings( $_POST );
1696
-
1697
- $ms_global_tables = array_merge( $wpdb->global_tables, $wpdb->ms_global_tables );
1698
- $tinfo = array();
1699
- $tprefix = $wpdb->prefix;
1700
- if ( $this->is_multisite() ) {
1701
- $tprefix = $wpdb->get_blog_prefix( $current_blog->blog_id );
1702
- }
1703
- $like_string = str_replace( '_', '\_', $tprefix ) . "%";
1704
- foreach ( $wpdb->get_results( $wpdb->prepare( "SHOW TABLE STATUS LIKE %s", $like_string ) ) as $row ) {
1705
- if ( $this->is_main_site() ) {
1706
- $matches = array();
1707
- preg_match( '/' . $tprefix . '(\d+)_/', $row->Name, $matches );
1708
- if ( isset( $matches[1] ) && (int) $current_blog->blog_id !== (int) $matches[1] )
1709
- continue;
1710
- }
1711
-
1712
- $table = preg_replace( '/^' . preg_quote( $wpdb->prefix ) . '/', '', $row->Name );
1713
-
1714
- if ( !$this->is_main_site() && $tprefix == $wpdb->prefix ) {
1715
- if ( in_array( $table, $ms_global_tables ) )
1716
- continue;
1717
- if ( preg_match( '/' . $tprefix . '(\d+)_/', $row->Name ) )
1718
- continue;
1719
- }
1720
-
1721
- $tinfo[$table] = array();
1722
- foreach ( (array)$row as $i => $v )
1723
- $tinfo[$table][$i] = $v;
1724
- if ( empty( $tinfo[$table] ) )
1725
- unset( $tinfo[$table] );
1726
- }
1727
-
1728
- if ( $this->is_main_site() ) {
1729
- foreach ( (array) $ms_global_tables as $ms_global_table ) {
1730
- $ms_table_status = $wpdb->get_row( $wpdb->prepare( "SHOW TABLE STATUS LIKE %s", $wpdb->base_prefix . $ms_global_table ) );
1731
- if ( !$ms_table_status )
1732
- continue;
1733
- $table = substr( $ms_table_status->Name, strlen( $wpdb->base_prefix ) );
1734
- $tinfo[$table] = array();
1735
- foreach ( (array) $ms_table_status as $i => $v )
1736
- $tinfo[$table][$i] = $v;
1737
- if ( empty( $tinfo[$table] ) )
1738
- unset( $tinfo[$table] );
1739
- }
1740
- }
1741
-
1742
- if ( isset( $_POST['php_ini'] ) && $_POST['php_ini'] == 1 )
1743
- $ini_vals = @ini_get_all();
1744
- else
1745
- $ini_vals = null;
1746
- if ( function_exists( 'sys_getloadavg' ) )
1747
- $loadavg = sys_getloadavg();
1748
- else
1749
- $loadavg = null;
1750
-
1751
- require_once ABSPATH . '/wp-admin/includes/plugin.php';
1752
- if ( function_exists( 'get_plugin_data' ) )
1753
- $vaultpress_response_info = get_plugin_data( __FILE__ );
1754
- else
1755
- $vaultpress_response_info = array( 'Version' => $this->plugin_version );
1756
- $vaultpress_response_info['deferred_pings'] = (int)$this->ai_ping_queue_size()->option_count;
1757
- $vaultpress_response_info['vaultpress_hostname'] = $this->get_option( 'hostname' );
1758
- $vaultpress_response_info['vaultpress_timeout'] = $this->get_option( 'timeout' );
1759
- $vaultpress_response_info['disable_firewall'] = $this->get_option( 'disable_firewall' );
1760
- $vaultpress_response_info['allow_forwarded_for'] = $this->get_option( 'allow_forwarded_for' );
1761
- $vaultpress_response_info['is_writable'] = is_writable( __FILE__ );
1762
-
1763
- $_wptype = 's';
1764
- if ( $this->is_multisite() ) {
1765
- global $wpmu_version;
1766
- if ( isset( $wpmu_version ) )
1767
- $_wptype = 'mu';
1768
- else
1769
- $_wptype = 'ms';
1770
- }
1771
-
1772
- $upload_url = '';
1773
- $upload_dir = wp_upload_dir();
1774
- if ( isset( $upload_dir['baseurl'] ) ) {
1775
- $upload_url = $upload_dir['baseurl'];
1776
- if ( false === strpos( $upload_url, 'http' ) )
1777
- $upload_url = untrailingslashit( site_url() ) . $upload_url;
1778
- }
1779
-
1780
- if ( defined( 'VP_DISABLE_UNAME' ) && VP_DISABLE_UNAME ) {
1781
- $uname_a = '';
1782
- $uname_n = '';
1783
- } else {
1784
- $uname_a = @php_uname( 'a' );
1785
- $uname_n = @php_uname( 'n' );
1786
- }
1787
-
1788
- $this->response( array(
1789
- 'vaultpress' => $vaultpress_response_info,
1790
- 'wordpress' => array(
1791
- 'wp_version' => $wp_version,
1792
- 'wp_db_version' => $wp_db_version,
1793
- 'locale' => get_locale(),
1794
- 'manifest_version' => $manifest_version,
1795
- 'prefix' => $wpdb->prefix,
1796
- 'is_multisite' => $this->is_multisite(),
1797
- 'is_main_site' => $this->is_main_site(),
1798
- 'blog_id' => isset( $current_blog ) ? $current_blog->blog_id : null,
1799
- 'theme' => (string) ( function_exists( 'wp_get_theme' ) ? wp_get_theme() : get_current_theme() ),
1800
- 'plugins' => preg_replace( '#/.*$#', '', get_option( 'active_plugins' ) ),
1801
- 'tables' => $tinfo,
1802
- 'name' => get_bloginfo( 'name' ),
1803
- 'upload_url' => $upload_url,
1804
- 'site_url' => $this->site_url(),
1805
- 'home_url' => ( function_exists( 'home_url' ) ? home_url() : get_option( 'home' ) ),
1806
- 'type' => $_wptype,
1807
- ),
1808
- 'server' => array(
1809
- 'host' => $_SERVER['HTTP_HOST'],
1810
- 'server' => $uname_n,
1811
- 'load' => $loadavg,
1812
- 'info' => $uname_a,
1813
- 'time' => time(),
1814
- 'php' => array( 'version' => phpversion(), 'ini' => $ini_vals, 'directory_separator' => DIRECTORY_SEPARATOR ),
1815
- 'httpd' => array(
1816
- 'type' => $httpd,
1817
- 'modules' => $http_modules,
1818
- ),
1819
- 'mysql' => $mvars,
1820
- ),
1821
- ) );
1822
- break;
1823
- case 'db:prefix':
1824
- $this->response( $wpdb->prefix );
1825
- break;
1826
- case 'db:wpdb':
1827
- if ( !$_POST['query'] )
1828
- die( "naughty naughty" );
1829
- $query = @base64_decode( $_POST['query'] );
1830
- if ( !$query )
1831
- die( "naughty naughty" );
1832
- if ( !$_POST['function'] )
1833
- $function = $function;
1834
- else
1835
- $function = $_POST['function'];
1836
- $this->response( $bdb->wpdb( $query, $function ) );
1837
- break;
1838
- case 'db:diff':
1839
- case 'db:count':
1840
- case 'db:cols':
1841
- if ( isset( $_POST['limit'] ) )
1842
- $limit = $_POST['limit'];
1843
- else
1844
- $limit = null;
1845
-
1846
- if ( isset( $_POST['offset'] ) )
1847
- $offset = $_POST['offset'];
1848
- else
1849
- $offset = null;
1850
-
1851
- if ( isset( $_POST['columns'] ) )
1852
- $columns = $_POST['columns'];
1853
- else
1854
- $columns = null;
1855
-
1856
- if ( isset( $_POST['signatures'] ) )
1857
- $signatures = $_POST['signatures'];
1858
- else
1859
- $signatures = null;
1860
-
1861
- if ( isset( $_POST['where'] ) )
1862
- $where = $_POST['where'];
1863
- else
1864
- $where = null;
1865
-
1866
- if ( isset( $_POST['table'] ) ) {
1867
- $parse_create_table = isset( $_POST['use_new_hash'] ) && $_POST['use_new_hash'] ? true : false;
1868
- $bdb->attach( base64_decode( $_POST['table'] ), $parse_create_table );
1869
- }
1870
-
1871
- $action_pieces = explode( ':', $_GET['action'] );
1872
- switch ( array_pop( $action_pieces ) ) {
1873
- case 'diff':
1874
- if ( !$signatures ) die( 'naughty naughty' );
1875
- // encoded because mod_security sees this as an SQL injection attack
1876
- $this->response( $bdb->diff( unserialize( base64_decode( $signatures ) ) ) );
1877
- case 'count':
1878
- if ( !$columns ) die( 'naughty naughty' );
1879
- $this->response( $bdb->count( unserialize( $columns ) ) );
1880
- case 'cols':
1881
- if ( !$columns ) die( 'naughty naughty' );
1882
- $this->response( $bdb->get_cols( unserialize( $columns ), $limit, $offset, $where ) );
1883
- }
1884
-
1885
- break;
1886
- case 'db:tables':
1887
- case 'db:explain':
1888
- case 'db:show_create':
1889
- if ( isset( $_POST['filter'] ) )
1890
- $filter = $_POST['filter'];
1891
- else
1892
- $filter = null;
1893
-
1894
- if ( isset( $_POST['table'] ) )
1895
- $bdb->attach( base64_decode( $_POST['table'] ) );
1896
-
1897
- $action_pieces = explode( ':', $_GET['action'] );
1898
- switch ( array_pop( $action_pieces ) ) {
1899
- default:
1900
- die( "naughty naughty" );
1901
- case 'tables':
1902
- $this->response( $bdb->get_tables( $filter ) );
1903
- case 'explain':
1904
- $this->response( $bdb->explain() );
1905
- case 'show_create':
1906
- $this->response( $bdb->show_create() );
1907
- }
1908
- break;
1909
- case 'db:restore':
1910
- if ( !empty( $_POST['path'] ) && isset( $_POST['hash'] ) ) {
1911
- $delete = !isset( $_POST['remove'] ) || $_POST['remove'] && 'false' !== $_POST['remove'];
1912
- $this->response( $bdb->restore( $_POST['path'], $_POST['hash'], $delete ) );
1913
- }
1914
- break;
1915
- case 'themes:active':
1916
- $this->response( get_option( 'current_theme' ) );
1917
- case 'plugins:active':
1918
- $this->response( preg_replace( '#/.*$#', '', get_option( 'active_plugins' ) ) );
1919
- break;
1920
- case 'plugins:checksum': case 'uploads:checksum': case 'themes:checksum': case 'content:checksum': case 'root:checksum':
1921
- case 'plugins:ls': case 'uploads:ls': case 'themes:ls': case 'content:ls': case 'root:ls':
1922
- case 'plugins:dir': case 'uploads:dir': case 'themes:dir': case 'content:dir': case 'root:dir':
1923
- case 'plugins:stat': case 'uploads:stat': case 'themes:stat': case 'content:stat': case 'root:stat':
1924
- case 'plugins:get': case 'uploads:get': case 'themes:get': case 'content:get': case 'root:get':
1925
-
1926
- $action_pieces = explode( ':', $_GET['action'] );
1927
- $bfs->want( array_shift( $action_pieces ) );
1928
-
1929
- if ( isset( $_POST['path'] ) )
1930
- $path = $_POST['path'];
1931
- else
1932
- $path = '';
1933
-
1934
- if ( !$bfs->validate( $path ) )
1935
- die( "naughty naughty" );
1936
-
1937
- if ( isset( $_POST['sha1'] ) && $_POST['sha1'] )
1938
- $sha1 = true;
1939
- else
1940
- $sha1 = false;
1941
-
1942
- if ( isset( $_POST['md5'] ) && $_POST['md5'] )
1943
- $md5 = true;
1944
- else
1945
- $md5 = false;
1946
-
1947
- if ( isset( $_POST['limit'] ) && $_POST['limit'] )
1948
- $limit=$_POST['limit'];
1949
- else
1950
- $limit = false;
1951
-
1952
- if ( isset( $_POST['offset'] ) && $_POST['offset'] )
1953
- $offset = $_POST['offset'];
1954
- else
1955
- $offset = false;
1956
-
1957
- if ( isset( $_POST['recursive'] ) )
1958
- $recursive = (bool)$_POST['recursive'];
1959
- else
1960
- $recursive = false;
1961
-
1962
- if ( isset( $_POST['full_list'] ) )
1963
- $full_list = (bool)$_POST['full_list'];
1964
- else
1965
- $full_list = false;
1966
-
1967
- $action_pieces = explode( ':', $_GET['action'] );
1968
- switch ( array_pop( $action_pieces ) ) {
1969
- default:
1970
- die( "naughty naughty" );
1971
- case 'checksum':
1972
- $list = array();
1973
- $this->response( $bfs->dir_checksum( $path, $list, $recursive ) );
1974
- case 'dir':
1975
- $this->response( $bfs->dir_examine( $path, $recursive ) );
1976
- case 'stat':
1977
- $this->response( $bfs->stat( $bfs->dir.$path ) );
1978
- case 'get':
1979
- $bfs->fdump( $bfs->dir.$path );
1980
- case 'ls':
1981
- $this->response( $bfs->ls( $path, $md5, $sha1, $limit, $offset, $full_list ) );
1982
- }
1983
- break;
1984
- case 'config:get':
1985
- if ( !isset( $_POST['key'] ) || !$_POST['key'] )
1986
- $this->response( false );
1987
- $key = '_vp_config_' . base64_decode( $_POST['key'] );
1988
- $this->response( base64_encode( maybe_serialize( $this->get_config( $key ) ) ) );
1989
- break;
1990
- case 'config:set':
1991
- if ( !isset( $_POST['key'] ) || !$_POST['key'] ) {
1992
- $this->response( false );
1993
- break;
1994
- }
1995
- $key = '_vp_config_' . base64_decode( $_POST['key'] );
1996
- if ( !isset( $_POST['val'] ) || !$_POST['val'] ) {
1997
- if ( !isset($_POST['delete']) || !$_POST['delete'] ) {
1998
- $this->response( false );
1999
- } else {
2000
- $this->response( delete_option( $key ) );
2001
- }
2002
- break;
2003
- }
2004
- $val = maybe_unserialize( base64_decode( $_POST['val'] ) );
2005
- $this->response( update_option( $key, $val ) );
2006
- break;
2007
- }
2008
- die();
2009
- }
2010
-
2011
- function _fix_ixr_null_to_string( &$args ) {
2012
- if ( is_array( $args ) )
2013
- foreach ( $args as $k => $v )
2014
- $args[$k] = $this->_fix_ixr_null_to_string( $v );
2015
- else if ( is_object( $args ) )
2016
- foreach ( get_object_vars( $args ) as $k => $v )
2017
- $args->$k = $this->_fix_ixr_null_to_string( $v );
2018
- else
2019
- return null == $args ? '' : $args;
2020
- return $args;
2021
- }
2022
-
2023
- function is_localhost() {
2024
- $site_url = $this->site_url();
2025
- if ( empty( $site_url ) )
2026
- return false;
2027
- $parts = parse_url( $site_url );
2028
- if ( !empty( $parts['host'] ) && in_array( $parts['host'], array( 'localhost', '127.0.0.1' ) ) )
2029
- return true;
2030
- return false;
2031
- }
2032
-
2033
- function contact_service( $action, $args = array() ) {
2034
- if ( 'test' != $action && 'register' != $action && !$this->check_connection() )
2035
- return false;
2036
-
2037
- global $current_user;
2038
- if ( !isset( $args['args'] ) )
2039
- $args['args'] = '';
2040
- $old_timeout = ini_get( 'default_socket_timeout' );
2041
- $timeout = $this->get_option( 'timeout' );
2042
- if ( function_exists( 'ini_set' ) )
2043
- ini_set( 'default_socket_timeout', $timeout );
2044
- $hostname = $this->get_option( 'hostname' );
2045
-
2046
- if ( !class_exists( 'VaultPress_IXR_SSL_Client' ) )
2047
- require_once( dirname( __FILE__ ) . '/class.vaultpress-ixr-ssl-client.php' );
2048
- $useragent = 'VaultPress/' . $this->plugin_version . '; ' . $this->site_url();
2049
- $client = new VaultPress_IXR_SSL_Client( $hostname, '/xmlrpc.php', 80, $timeout, $useragent );
2050
-
2051
- if ( 'vaultpress.com' == $hostname )
2052
- $client->ssl();
2053
-
2054
- // Begin audit trail breadcrumbs
2055
- if ( isset( $current_user ) && is_object( $current_user ) && isset( $current_user->ID ) ) {
2056
- $args['cause_user_id'] = intval( $current_user->ID );
2057
- $args['cause_user_login'] = (string)$current_user->user_login;
2058
- } else {
2059
- $args['cause_user_id'] = -1;
2060
- $args['cause_user_login'] = '';
2061
- }
2062
- $args['cause_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null ;
2063
- $args['cause_uri'] = isset( $_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null;
2064
- $args['cause_method'] = isset( $_SERVER['REQUEST_METHOD'] ) ? $_SERVER['REQUEST_METHOD'] : null;
2065
- // End audit trail breadcrumbs
2066
-
2067
- $args['version'] = $this->plugin_version;
2068
- $args['locale'] = get_locale();
2069
- $args['site_url'] = $this->site_url();
2070
-
2071
- $salt = md5( time() . serialize( $_SERVER ) );
2072
- $args['key'] = $this->get_option( 'key' );
2073
- $this->_fix_ixr_null_to_string( $args );
2074
- $args['signature'] = $this->sign_string( serialize( $args ), $this->get_option( 'secret' ), $salt ).":$salt";
2075
-
2076
- $client->query( 'vaultpress.'.$action, new IXR_Base64( serialize( $args ) ) );
2077
- $rval = $client->message ? $client->getResponse() : '';
2078
- if ( function_exists( 'ini_set' ) )
2079
- ini_set( 'default_socket_timeout', $old_timeout );
2080
-
2081
- // we got an error from the servers
2082
- if ( is_array( $rval ) && isset( $rval['faultCode'] ) ) {
2083
- $this->update_option( 'connection', time() );
2084
- $this->update_option( 'connection_error_code', $rval['faultCode'] );
2085
- $this->update_option( 'connection_error_message', $rval['faultString'] );
2086
- }
2087
-
2088
- return $rval;
2089
- }
2090
-
2091
- function validate_api_signature() {
2092
- global $__vp_validate_error;
2093
- if ( !empty( $_POST['signature'] ) ) {
2094
- if ( is_string( $_POST['signature'] ) ) {
2095
- $sig = $_POST['signature'];
2096
- } else {
2097
- $__vp_validate_error = array( 'error' => 'invalid_signature_format' );
2098
- return false;
2099
- }
2100
- } else {
2101
- $__vp_validate_error = array( 'error' => 'no_signature' );
2102
- return false;
2103
- }
2104
-
2105
- $secret = $this->get_option( 'secret' );
2106
- if ( !$secret ) {
2107
- $__vp_validate_error = array( 'error' => 'missing_secret' );
2108
- return false;
2109
- }
2110
- if ( !$this->get_option( 'disable_firewall' ) ) {
2111
- if ( ! $this->check_firewall() )
2112
- return false;
2113
- }
2114
- $sig = explode( ':', $sig );
2115
- if ( !is_array( $sig ) || count( $sig ) != 2 || !isset( $sig[0] ) || !isset( $sig[1] ) ) {
2116
- $__vp_validate_error = array( 'error' => 'invalid_signature_format' );
2117
- return false;
2118
- }
2119
-
2120
- // Pass 1 -- new method
2121
- $uri = preg_replace( '/^[^?]+\?/', '?', $_SERVER['REQUEST_URI'] );
2122
- $post = $_POST;
2123
- unset( $post['signature'] );
2124
- // Work around for dd-formmailer plugin
2125
- if ( isset( $post['_REPEATED'] ) )
2126
- unset( $post['_REPEATED'] );
2127
- ksort( $post );
2128
- $to_sign = serialize( array( 'uri' => $uri, 'post' => $post ) );
2129
-
2130
- if ( $this->can_use_openssl() ) {
2131
- $sslsig = '';
2132
- if ( isset( $post['sslsig'] ) ) {
2133
- $sslsig = $post['sslsig'];
2134
- unset( $post['sslsig'] );
2135
- }
2136
- if ( 1 === openssl_verify( serialize( array( 'uri' => $uri, 'post' => $post ) ), base64_decode( $sslsig ), $this->get_option( 'public_key' ) ) ) {
2137
- return true;
2138
- } else {
2139
- $__vp_validate_error = array( 'error' => 'invalid_signed_data' );
2140
- return false;
2141
- }
2142
- }
2143
-
2144
- $signature = $this->sign_string( $to_sign, $secret, $sig[1] );
2145
- if ( hash_equals( $sig[0], $signature ) ) {
2146
- return true;
2147
- }
2148
-
2149
- $__vp_validate_error = array( 'error' => 'invalid_signed_data' );
2150
- return false;
2151
- }
2152
-
2153
- function ip_in_cidr( $ip, $cidr ) {
2154
- list ($net, $mask) = explode( '/', $cidr );
2155
- return ( ip2long( $ip ) & ~((1 << (32 - $mask)) - 1) ) == ( ip2long( $net ) & ~((1 << (32 - $mask)) - 1) );
2156
- }
2157
-
2158
- function ip_in_cidrs( $ip, $cidrs ) {
2159
- foreach ( (array)$cidrs as $cidr ) {
2160
- if ( $this->ip_in_cidr( $ip, $cidr ) ) {
2161
- return $cidr;
2162
- }
2163
- }
2164
-
2165
- return false;
2166
- }
2167
-
2168
- function check_firewall() {
2169
- global $__vp_validate_error;
2170
-
2171
- $stored_cidrs = $this->get_option( 'service_ips_cidr' );
2172
- $stored_ext_cidrs = get_option( 'vaultpress_service_ips_external_cidr' );
2173
-
2174
- $one_day_ago = time() - 86400;
2175
- if ( empty( $stored_cidrs ) || empty( $stored_ext_cidrs ) || $stored_cidrs['updated'] < $one_day_ago ) {
2176
- $cidrs = $this->update_firewall();
2177
- }
2178
-
2179
- if ( empty( $cidrs ) ) {
2180
- $cidrs = array_merge( $stored_cidrs['data'], $stored_ext_cidrs['data'] );
2181
- }
2182
-
2183
- if ( empty( $cidrs ) ) {
2184
- // No up-to-date info; fall back on the old methods.
2185
- if ( $this->do_c_block_firewall() ) {
2186
- return true;
2187
- } else {
2188
- $__vp_validate_error = array( 'error' => 'empty_vp_ip_cidr_range' );
2189
- return false;
2190
- }
2191
- }
2192
-
2193
- // Figure out possible remote IPs
2194
- $remote_ips = array();
2195
- if ( !empty( $_SERVER['REMOTE_ADDR'] ) )
2196
- $remote_ips['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
2197
-
2198
- // If this is a pingback during a connection test, search for valid-looking ips among headers
2199
- $connection_test_key = $this->get_option( 'connection_test' );
2200
- $testing_all_headers = ( ! empty( $_POST['test_key'] ) && $_POST['test_key'] === $connection_test_key );
2201
- if ( $testing_all_headers ) {
2202
- $remote_ips = array_filter( $_SERVER, array( $this, 'looks_like_ip_list' ) );
2203
- }
2204
-
2205
- // If there is a pre-configured forwarding IP header, check that.
2206
- $forward_header = $this->get_option( 'allow_forwarded_for' );
2207
- if ( true === $forward_header || 1 == $forward_header ) {
2208
- $forward_header = 'HTTP_X_FORWARDED_FOR';
2209
- }
2210
- if ( ! empty( $forward_header ) && ! empty( $_SERVER[ $forward_header ] ) ) {
2211
- $remote_ips[ $forward_header ] = $_SERVER[ $forward_header ];
2212
- }
2213
-
2214
- if ( empty( $remote_ips ) ) {
2215
- $__vp_validate_error = array( 'error' => 'no_remote_addr', 'detail' => (int) $this->get_option( 'allow_forwarded_for' ) ); // shouldn't happen
2216
- return false;
2217
- }
2218
-
2219
- foreach ( $remote_ips as $header_name => $ip_list ) {
2220
- $ips = explode( ',', $ip_list );
2221
- foreach ( $ips as $ip ) {
2222
- $ip = preg_replace( '#^::(ffff:)?#', '', $ip );
2223
- if ( $cidr = $this->ip_in_cidrs( $ip, $cidrs ) ) {
2224
- // Successful match found. If testing all headers, note the successful header.
2225
- if ( $testing_all_headers && 'REMOTE_ADDR' !== $header_name ) {
2226
- $this->update_option( 'allow_forwarded_for', $header_name );
2227
- }
2228
-
2229
- return true;
2230
- }
2231
- }
2232
- }
2233
-
2234
- $__vp_validate_error = array( 'error' => 'remote_addr_fail', 'detail' => $remote_ips );
2235
- return false;
2236
- }
2237
-
2238
- // Returns true if $value looks like a comma-separated list of IPs
2239
- function looks_like_ip_list( $value ) {
2240
- if ( ! is_string( $value ) ) {
2241
- return false;
2242
- }
2243
-
2244
- $items = explode( ',', $value );
2245
- foreach ( $items as $item ) {
2246
- if ( ip2long( $item ) === false ) {
2247
- return false;
2248
- }
2249
- }
2250
-
2251
- return true;
2252
- }
2253
-
2254
- function do_c_block_firewall() {
2255
- // Perform the firewall check by class-c ip blocks
2256
- $rxs = $this->get_option( 'service_ips' );
2257
- $service_ips_external = get_option( 'vaultpress_service_ips_external' );
2258
-
2259
- if ( !empty( $rxs['data'] ) && !empty( $service_ips_external['data'] ) )
2260
- $rxs = array_merge( $rxs['data'], $service_ips_external['data'] );
2261
- if ( ! $rxs )
2262
- return false;
2263
- return $this->validate_ip_address( $rxs );
2264
- }
2265
-
2266
- function validate_ip_address( $rxs ) {
2267
- global $__vp_validate_error;
2268
- if ( empty( $rxs ) ) {
2269
- $__vp_validate_error = array( 'error' => 'empty_vp_ip_range' );
2270
- return false;
2271
- }
2272
-
2273
- $remote_ips = array();
2274
-
2275
- if ( $this->get_option( 'allow_forwarded_for') && !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
2276
- $remote_ips = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
2277
-
2278
- if ( !empty( $_SERVER['REMOTE_ADDR'] ) )
2279
- $remote_ips[] = $_SERVER['REMOTE_ADDR'];
2280
-
2281
- if ( empty( $remote_ips ) ) {
2282
- $__vp_validate_error = array( 'error' => 'no_remote_addr', 'detail' => (int) $this->get_option( 'allow_forwarded_for' ) ); // shouldn't happen
2283
- return false;
2284
- }
2285
-
2286
- $iprx = '/^([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/';
2287
-
2288
- foreach ( $remote_ips as $_remote_ip ) {
2289
- $remote_ip = preg_replace( '#^::(ffff:)?#', '', $_remote_ip );
2290
- if ( !preg_match( $iprx, $remote_ip, $r ) ) {
2291
- $__vp_validate_error = array( 'error' => "remote_addr_fail", 'detail' => $_remote_ip );
2292
- return false;
2293
- }
2294
-
2295
- foreach ( (array)$rxs as $begin => $end ) {
2296
- if ( !preg_match( $iprx, $begin, $b ) )
2297
- continue;
2298
- if ( !preg_match( $iprx, $end, $e ) )
2299
- continue;
2300
- if ( $r[1] != $b[1] || $r[1] != $e[1] )
2301
- continue;
2302
- $me = $r[2];
2303
- $b = min( (int)$b[2], (int)$e[2] );
2304
- $e = max( (int)$b[2], (int)$e[2] );
2305
- if ( $me >= $b && $me <= $e ) {
2306
- return true;
2307
- }
2308
- }
2309
- }
2310
- $__vp_validate_error = array( 'error' => 'remote_addr_fail', 'detail' => $remote_ips );
2311
-
2312
- return false;
2313
- }
2314
-
2315
- function sign_string( $string, $secret, $salt ) {
2316
- return hash_hmac( 'sha1', "$string:$salt", $secret );
2317
- }
2318
-
2319
- function can_use_openssl() {
2320
- if ( !function_exists( 'openssl_verify' ) )
2321
- return false;
2322
- $pk = $this->get_option( 'public_key' );
2323
- if ( empty( $pk ) )
2324
- return false;
2325
- if ( 1 !== (int) $this->get_option( 'use_openssl_signing' ) )
2326
- return false;
2327
- return true;
2328
- }
2329
-
2330
- function response( $response, $raw = false ) {
2331
- // "re" -- "Response Encoding"
2332
- if ( !empty( $_GET['re'] ) )
2333
- header( sprintf( 'X-VP-Encoded: X%d', abs( intval( $_GET['re'] ) ) ) );
2334
- if ( $raw ) {
2335
- if ( !isset( $_GET['re'] ) )
2336
- die( $response );
2337
- else if ( '1' === $_GET['re'] )
2338
- die( base64_encode( $response ) );
2339
- else if ( '2' === $_GET['re'] )
2340
- die( str_rot13( $response ) );
2341
- else
2342
- die( $response );
2343
- }
2344
- list( $usec, $sec ) = explode( " ", microtime() );
2345
- $r = new stdClass();
2346
- $r->req_vector = floatval( $_GET['vector'] );
2347
- $r->rsp_vector = ( (float)$usec + (float)$sec );
2348
- if ( function_exists( "getrusage" ) )
2349
- $r->rusage = getrusage();
2350
- else
2351
- $r->rusage = false;
2352
- if ( function_exists( "memory_get_peak_usage" ) )
2353
- $r->peak_memory_usage = memory_get_peak_usage( true );
2354
- else
2355
- $r->peak_memory_usage = false;
2356
- if ( function_exists( "memory_get_usage" ) )
2357
- $r->memory_usage = memory_get_usage( true );
2358
- else
2359
- $r->memory_usage = false;
2360
- $r->response = $response;
2361
- if ( !isset( $_GET['re'] ) )
2362
- die( serialize( $r ) );
2363
- else if ( '1' === $_GET['re'] )
2364
- die( base64_encode( serialize( $r ) ) );
2365
- else if ( '2' === $_GET['re'] )
2366
- die( str_rot13( serialize( $r ) ) );
2367
- else
2368
- die( serialize( $r ) );
2369
- }
2370
-
2371
- function reset_pings() {
2372
- global $vaultpress_pings;
2373
- $vaultpress_pings = array(
2374
- 'version' => 1,
2375
- 'count' => 0,
2376
- 'editedtables' => array(),
2377
- 'plugins' => array(),
2378
- 'themes' => array(),
2379
- 'uploads' => array(),
2380
- 'db' => array(),
2381
- 'debug' => array(),
2382
- 'security' => array(),
2383
- );
2384
- }
2385
-
2386
- function add_ping( $type, $data, $hook=null ) {
2387
- global $vaultpress_pings;
2388
- if ( defined( 'WP_IMPORTING' ) && constant( 'WP_IMPORTING' ) )
2389
- return;
2390
- if ( isset( $_GET ) && isset( $_GET['comment_status'] ) && isset( $_GET['delete_all'] ) && 'spam' == $_GET['comment_status'] )
2391
- return; // Skip pings from mass spam delete.
2392
- if ( !array_key_exists( $type, $vaultpress_pings ) )
2393
- return;
2394
-
2395
- switch( $type ) {
2396
- case 'editedtables';
2397
- $vaultpress_pings[$type] = $data;
2398
- return;
2399
- case 'uploads':
2400
- case 'themes':
2401
- case 'plugins':
2402
- if ( !is_array( $data ) ) {
2403
- $data = array( $data );
2404
- }
2405
- foreach ( $data as $val ) {
2406
- if ( in_array( $data, $vaultpress_pings[$type] ) )
2407
- continue;
2408
- $vaultpress_pings['count']++;
2409
- $vaultpress_pings[$type][]=$val;
2410
- }
2411
- return;
2412
- case 'db':
2413
- $_keys = array_keys( $data );
2414
- $subtype = array_shift( $_keys );
2415
- if ( !isset( $vaultpress_pings[$type][$subtype] ) )
2416
- $vaultpress_pings[$type][$subtype] = array();
2417
- if ( in_array( $data, $vaultpress_pings[$type][$subtype] ) )
2418
- return;
2419
- $vaultpress_pings['count']++;
2420
- $vaultpress_pings[$type][$subtype][] = $data;
2421
- return;
2422
- default:
2423
- if ( in_array( $data, $vaultpress_pings[$type] ) )
2424
- return;
2425
- $vaultpress_pings['count']++;
2426
- $vaultpress_pings[$type][] = $data;
2427
- return;
2428
- }
2429
- }
2430
-
2431
- function do_pings() {
2432
- global $wpdb, $vaultpress_pings, $__vp_recursive_ping_lock;
2433
- if ( defined( 'WP_IMPORTING' ) && constant( 'WP_IMPORTING' ) )
2434
- return;
2435
-
2436
- if ( !isset( $wpdb ) ) {
2437
- $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2438
- $close_wpdb = true;
2439
- } else {
2440
- $close_wpdb = false;
2441
- }
2442
-
2443
- if ( !$vaultpress_pings['count'] )
2444
- return;
2445
-
2446
- // Short circuit the contact process if we know that we can't contact the service
2447
- if ( isset( $__vp_recursive_ping_lock ) && $__vp_recursive_ping_lock ) {
2448
- $this->ai_ping_insert( serialize( $vaultpress_pings ) );
2449
- if ( $close_wpdb ) {
2450
- $wpdb->__destruct();
2451
- unset( $wpdb );
2452
- }
2453
- $this->reset_pings();
2454
- return;
2455
- }
2456
-
2457
- $ping_attempts = 0;
2458
- do {
2459
- $ping_attempts++;
2460
- $rval = $this->contact_service( 'ping', array( 'args' => $vaultpress_pings ) );
2461
- if ( $rval || $ping_attempts >= 3 )
2462
- break;
2463
- if ( !$rval )
2464
- usleep(500000);
2465
- } while ( true );
2466
- if ( !$rval ) {
2467
- if ( $this->get_option( 'connection_error_code' ) !== -8 ) { // Do not save pings when the subscription is inactive.
2468
- $__vp_recursive_ping_lock = true;
2469
- $this->ai_ping_insert( serialize( $vaultpress_pings ) );
2470
- }
2471
- }
2472
- $this->reset_pings();
2473
- if ( $close_wpdb ) {
2474
- $wpdb->__destruct();
2475
- unset( $wpdb );
2476
- }
2477
- return $rval;
2478
- }
2479
-
2480
- function resolve_content_dir() {
2481
- // Take the easy way out
2482
- if ( defined( 'WP_CONTENT_DIR' ) ) {
2483
- if ( substr( WP_CONTENT_DIR, -1 ) != DIRECTORY_SEPARATOR )
2484
- return WP_CONTENT_DIR . DIRECTORY_SEPARATOR;
2485
- return WP_CONTENT_DIR;
2486
- }
2487
- // Best guess
2488
- if ( defined( 'ABSPATH' ) ) {
2489
- if ( substr( ABSPATH, -1 ) != DIRECTORY_SEPARATOR )
2490
- return ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR;
2491
- return ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR;
2492
- }
2493
- // Run with a solid assumption: WP_CONTENT_DIR/vaultpress/vaultpress.php
2494
- return dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR;
2495
- }
2496
-
2497
- function resolve_upload_path() {
2498
- $upload_path = false;
2499
- $upload_dir = wp_upload_dir();
2500
-
2501
- if ( isset( $upload_dir['basedir'] ) )
2502
- $upload_path = $upload_dir['basedir'];
2503
-
2504
- // Nothing recorded? use a best guess!
2505
- if ( !$upload_path || $upload_path == realpath( ABSPATH ) )
2506
- return $this->resolve_content_dir() . 'uploads' . DIRECTORY_SEPARATOR;
2507
-
2508
- if ( substr( $upload_path, -1 ) != DIRECTORY_SEPARATOR )
2509
- $upload_path .= DIRECTORY_SEPARATOR;
2510
-
2511
- return $upload_path;
2512
- }
2513
-
2514
- function load_first( $value ) {
2515
- $value = array_unique( $value ); // just in case there are duplicates
2516
- return array_merge(
2517
- preg_grep( '/vaultpress\.php$/', $value ),
2518
- preg_grep( '/vaultpress\.php$/', $value, PREG_GREP_INVERT )
2519
- );
2520
- }
2521
-
2522
- function is_multisite() {
2523
- if ( function_exists( 'is_multisite' ) )
2524
- return is_multisite();
2525
-
2526
- return false;
2527
- }
2528
-
2529
- function is_main_site() {
2530
- if ( !function_exists( 'is_main_site' ) || !$this->is_multisite() )
2531
- return true;
2532
-
2533
- return is_main_site();
2534
- }
2535
-
2536
- function is_registered() {
2537
- $key = $this->get_option( 'key' );
2538
- $secret = $this->get_option( 'secret' );
2539
- return !empty( $key ) && !empty( $secret );
2540
- }
2541
-
2542
- function clear_connection() {
2543
- $this->delete_option( 'connection' );
2544
- $this->delete_option( 'connection_error_code' );
2545
- $this->delete_option( 'connection_error_message' );
2546
- $this->delete_option( 'connection_test' );
2547
- }
2548
-
2549
- function site_url() {
2550
- $site_url = '';
2551
-
2552
- // compatibility for WordPress MU Domain Mapping plugin
2553
- if ( defined( 'DOMAIN_MAPPING' ) && DOMAIN_MAPPING && ! function_exists( 'domain_mapping_siteurl' ) ) {
2554
- if ( !function_exists( 'is_plugin_active' ) )
2555
- require_once ABSPATH . '/wp-admin/includes/plugin.php';
2556
-
2557
- $plugin = 'wordpress-mu-domain-mapping/domain_mapping.php';
2558
- if ( is_plugin_active( $plugin ) )
2559
- include_once( WP_PLUGIN_DIR . '/' . $plugin );
2560
- }
2561
-
2562
- if ( function_exists( 'domain_mapping_siteurl' ) )
2563
- $site_url = domain_mapping_siteurl( false );
2564
-
2565
- if ( empty( $site_url ) )
2566
- $site_url = site_url();
2567
-
2568
- return $site_url;
2569
- }
2570
-
2571
- /**
2572
- * Sync the VaultPress options to WordPress.com if the Jetpack plugin is active.
2573
- */
2574
- function sync_jetpack_options() {
2575
- if ( class_exists( 'Jetpack_Sync' ) && method_exists( 'Jetpack_Sync', 'sync_options' ) && defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '4.1', '<' ) ) {
2576
- Jetpack_Sync::sync_options( __FILE__, $this->auto_register_option, $this->option_name );
2577
- }
2578
- }
2579
-
2580
- /**
2581
- * Add the VaultPress options to the Jetpack options management whitelist.
2582
- * Allows Jetpack to register VaultPress options automatically.
2583
- *
2584
- * @param array $options The list of whitelisted option names.
2585
- *
2586
- * @return array The updated whitelist
2587
- */
2588
- function add_to_jetpack_options_whitelist( $options ) {
2589
- $options[] = $this->option_name;
2590
- $options[] = $this->auto_register_option;
2591
-
2592
- return $options;
2593
- }
2594
-
2595
- /**
2596
- * When the VaultPress auto-register option is updated, run the registration call.
2597
- *
2598
- * This should only be run when the option is updated from the Jetpack/WP.com
2599
- * API call, and only if the new key is different than the old key.
2600
- *
2601
- * @param mixed $old_value The old option value, or the option name (if add_option).
2602
- * @param mixed $value The new option value.
2603
- */
2604
- function updated_auto_register_option( $old_value, $value ) {
2605
- // Not an API call or CLI call
2606
- if ( ! class_exists( 'WPCOM_JSON_API_Update_Option_Endpoint' ) && ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
2607
- return;
2608
- }
2609
-
2610
- remove_action( "update_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ) );
2611
-
2612
- $defaults = array(
2613
- 'key' => false,
2614
- 'action' => 'register', // or `response`
2615
- 'status' => 'working',
2616
- 'error' => false,
2617
- );
2618
-
2619
- // `wp_parse_args` uses arrays, might as well be explicit about it.
2620
- $registration = (array) json_decode( $value );
2621
- $registration = wp_parse_args( $registration, $defaults );
2622
-
2623
- // If we have a working connection, don't update the key.
2624
- if ( $this->check_connection( true ) ) {
2625
- $registration['action'] = 'response';
2626
- $registration['error'] = 'VaultPress is already registered on this site.';
2627
- update_option( $this->auto_register_option, json_encode( $registration ) );
2628
- return;
2629
- }
2630
-
2631
- if ( ! $registration['key'] ) {
2632
- return;
2633
- }
2634
-
2635
- $registration['action'] = 'response';
2636
-
2637
- $response = $this->register( $registration['key'] );
2638
- if ( is_wp_error( $response ) ) {
2639
- $registration['status'] = 'broken';
2640
- $registration['error'] = $response->get_error_message();
2641
- } else if ( $this->get_option( 'connection_error_code' ) ) {
2642
- $registration['status'] = 'broken';
2643
- $registration['error'] = $this->get_option( 'connection_error_message' );
2644
- } else {
2645
- $registration['error'] = false;
2646
- }
2647
-
2648
- update_option( $this->auto_register_option, json_encode( $registration ) );
2649
- }
2650
-
2651
- function add_global_actions_and_filters() {
2652
- add_action( 'init', array( $this, 'sync_jetpack_options' ), 0, 99 );
2653
- add_filter( 'jetpack_options_whitelist', array( $this, 'add_to_jetpack_options_whitelist' ) );
2654
- add_action( "update_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ), 10, 2 );
2655
- add_action( "add_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ), 10, 2 );
2656
- add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
2657
- }
2658
-
2659
- function add_admin_actions_and_filters() {
2660
- add_action( 'admin_init', array( $this, 'admin_init' ) );
2661
- add_action( 'admin_menu', array( $this, 'admin_menu' ), 5 ); # Priority 5, so it's called before Jetpack's admin_menu.
2662
- add_action( 'admin_head', array( $this, 'admin_head' ) );
2663
- }
2664
-
2665
- function add_listener_actions_and_filters() {
2666
- add_action( 'admin_bar_menu', array( $this, 'toolbar' ), 999 );
2667
-
2668
- // Comments
2669
- add_action( 'delete_comment', array( $this, 'comment_action_handler' ) );
2670
- add_action( 'wp_set_comment_status', array( $this, 'comment_action_handler' ) );
2671
- add_action( 'trashed_comment', array( $this, 'comment_action_handler' ) );
2672
- add_action( 'untrashed_comment', array( $this, 'comment_action_handler' ) );
2673
- add_action( 'wp_insert_comment', array( $this, 'comment_action_handler' ) );
2674
- add_action( 'comment_post', array( $this, 'comment_action_handler' ) );
2675
- add_action( 'edit_comment', array( $this, 'comment_action_handler' ) );
2676
-
2677
- // Commentmeta
2678
- add_action( 'added_comment_meta', array( $this, 'commentmeta_insert_handler' ), 10, 2 );
2679
- add_action( 'updated_comment_meta', array( $this, 'commentmeta_modification_handler' ), 10, 4 );
2680
- add_action( 'deleted_comment_meta', array( $this, 'commentmeta_modification_handler' ), 10, 4 );
2681
-
2682
- // Users
2683
- if ( $this->is_main_site() ) {
2684
- add_action( 'user_register', array( $this, 'userid_action_handler' ) );
2685
- add_action( 'password_reset', array( $this, 'userid_action_handler' ) );
2686
- add_action( 'profile_update', array( $this, 'userid_action_handler' ) );
2687
- add_action( 'user_register', array( $this, 'userid_action_handler' ) );
2688
- add_action( 'deleted_user', array( $this, 'userid_action_handler' ) );
2689
- }
2690
-
2691
- // Usermeta
2692
- if ( $this->is_main_site() ) {
2693
- add_action( 'added_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2694
- add_action( 'update_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2695
- add_action( 'delete_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2696
- }
2697
-
2698
- // Posts
2699
- add_action( 'delete_post', array( $this, 'post_action_handler' ) );
2700
- add_action( 'trash_post', array( $this, 'post_action_handler' ) );
2701
- add_action( 'untrash_post', array( $this, 'post_action_handler' ) );
2702
- add_action( 'edit_post', array( $this, 'post_action_handler' ) );
2703
- add_action( 'save_post', array( $this, 'post_action_handler' ) );
2704
- add_action( 'wp_insert_post', array( $this, 'post_action_handler' ) );
2705
- add_action( 'edit_attachment', array( $this, 'post_action_handler' ) );
2706
- add_action( 'add_attachment', array( $this, 'post_action_handler' ) );
2707
- add_action( 'delete_attachment', array( $this, 'post_action_handler' ) );
2708
- add_action( 'private_to_published', array( $this, 'post_action_handler' ) );
2709
- add_action( 'wp_restore_post_revision', array( $this, 'post_action_handler' ) );
2710
-
2711
- // Postmeta
2712
- add_action( 'added_post_meta', array( $this, 'postmeta_insert_handler' ), 10, 4 );
2713
- add_action( 'update_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2714
- add_action( 'updated_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2715
- add_action( 'delete_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2716
- add_action( 'deleted_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2717
- add_action( 'added_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2718
- add_action( 'update_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2719
- add_action( 'delete_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2720
-
2721
- // Links
2722
- add_action( 'edit_link', array( $this, 'link_action_handler' ) );
2723
- add_action( 'add_link', array( $this, 'link_action_handler' ) );
2724
- add_action( 'delete_link', array( $this, 'link_action_handler' ) );
2725
-
2726
- // Taxonomy
2727
- add_action( 'created_term', array( $this, 'term_handler' ), 2 );
2728
- add_action( 'edited_terms', array( $this, 'term_handler' ), 2 );
2729
- add_action( 'delete_term', array( $this, 'term_handler' ), 2 );
2730
- add_action( 'edit_term_taxonomy', array( $this, 'term_taxonomy_handler' ) );
2731
- add_action( 'delete_term_taxonomy', array( $this, 'term_taxonomy_handler' ) );
2732
- add_action( 'edit_term_taxonomies', array( $this, 'term_taxonomies_handler' ) );
2733
- add_action( 'add_term_relationship', array( $this, 'term_relationship_handler' ), 10, 2 );
2734
- add_action( 'delete_term_relationships', array( $this, 'term_relationships_handler' ), 10, 2 );
2735
- add_action( 'set_object_terms', array( $this, 'set_object_terms_handler' ), 10, 3 );
2736
-
2737
- // Files
2738
- if ( $this->is_main_site() ) {
2739
- add_action( 'switch_theme', array( $this, 'theme_action_handler' ) );
2740
- add_action( 'activate_plugin', array( $this, 'plugin_action_handler' ) );
2741
- add_action( 'deactivate_plugin', array( $this, 'plugin_action_handler' ) );
2742
- }
2743
- add_action( 'wp_handle_upload', array( $this, 'upload_handler' ) );
2744
-
2745
- // Options
2746
- add_action( 'deleted_option', array( $this, 'option_handler' ), 1 );
2747
- add_action( 'updated_option', array( $this, 'option_handler' ), 1 );
2748
- add_action( 'added_option', array( $this, 'option_handler' ), 1 );
2749
-
2750
- $this->add_woocommerce_actions();
2751
- $this->add_vp_required_filters();
2752
- }
2753
-
2754
- function add_woocommerce_actions() {
2755
- add_action( 'woocommerce_tax_rate_deleted', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2756
- add_action( 'woocommerce_tax_rate_updated', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2757
- add_action( 'woocommerce_tax_rate_added', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2758
-
2759
- add_action( 'woocommerce_new_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2760
- add_action( 'woocommerce_update_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2761
- add_action( 'woocommerce_delete_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2762
-
2763
- add_action( 'added_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2764
- add_action( 'updated_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2765
- add_action( 'deleted_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2766
-
2767
- add_action( 'woocommerce_attribute_added', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2768
- add_action( 'woocommerce_attribute_updated', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2769
- add_action( 'woocommerce_attribute_deleted', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2770
- }
2771
-
2772
- function add_vp_required_filters() {
2773
- // Log ins
2774
- if ( $this->get_option( 'login_lockdown' ) ) {
2775
- add_action( 'login_form', array( $this, 'add_js_token' ) );
2776
- add_filter( 'authenticate', array( $this, 'authenticate' ), 999 );
2777
- }
2778
-
2779
- // Report back to VaultPress
2780
- add_action( 'shutdown', array( $this, 'do_pings' ) );
2781
-
2782
- // VaultPress likes being first in line
2783
- add_filter( 'pre_update_option_active_plugins', array( $this, 'load_first' ) );
2784
- }
2785
-
2786
- function get_jetpack_email() {
2787
- if ( !class_exists('Jetpack') )
2788
- return false;
2789
-
2790
- Jetpack::load_xml_rpc_client();
2791
- $xml = new Jetpack_IXR_Client( array( 'user_id' => get_current_user_id() ) );
2792
- $xml->query( 'wpcom.getUserEmail' );
2793
- if ( ! $xml->isError() ) {
2794
- return $xml->getResponse();
2795
- }
2796
-
2797
- return new WP_Error( $xml->getErrorCode(), $xml->getErrorMessage() );
2798
- }
2799
-
2800
- function get_key_via_jetpack( $already_purchased = false ) {
2801
- if ( !class_exists('Jetpack') )
2802
- return false;
2803
-
2804
- Jetpack::load_xml_rpc_client();
2805
- $xml = new Jetpack_IXR_Client( array( 'user_id' => Jetpack_Options::get_option( 'master_user' ) ) );
2806
- $xml->query( 'vaultpress.registerSite', $already_purchased );
2807
- if ( ! $xml->isError() ) {
2808
- return $xml->getResponse();
2809
- }
2810
-
2811
- return new WP_Error( $xml->getErrorCode(), $xml->getErrorMessage() );
2812
- }
2813
-
2814
- function register_via_jetpack( $already_purchased = false ) {
2815
- $registration_key = $this->get_key_via_jetpack( $already_purchased );
2816
- if ( is_wp_error( $registration_key ) ) {
2817
- return $registration_key;
2818
- }
2819
-
2820
- return self::register( $registration_key );
2821
- }
2822
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: automattic, apokalyptik, briancolinger, josephscott, shaunandrews,
3
  Tags: security, malware, virus, archive, back up, back ups, backup, backups, scanning, restore, wordpress backup, site backup, website backup
4
  Requires at least: 5.1
5
  Tested up to: 5.2
6
- Stable tag: 2.0
7
  Requires PHP: 5.3
8
  License: GPLv2
9
 
@@ -49,6 +49,14 @@ Yes, VaultPress supports Multisite installs. Each site will require its own subs
49
 
50
  == Changelog ==
51
 
 
 
 
 
 
 
 
 
52
  = 2.0 =
53
 
54
  * Release date: July 9, 2019
3
  Tags: security, malware, virus, archive, back up, back ups, backup, backups, scanning, restore, wordpress backup, site backup, website backup
4
  Requires at least: 5.1
5
  Tested up to: 5.2
6
+ Stable tag: 2.0.1
7
  Requires PHP: 5.3
8
  License: GPLv2
9
 
49
 
50
  == Changelog ==
51
 
52
+ = 2.0.1 =
53
+
54
+ * Release date: July 12, 2019
55
+
56
+ **Bug Fixes**
57
+
58
+ * Security Scanner: ensure the Security Scanner can be triggered at all times.
59
+
60
  = 2.0 =
61
 
62
  * Release date: July 9, 2019
vaultpress.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: VaultPress
4
  * Plugin URI: http://vaultpress.com/?utm_source=plugin-uri&amp;utm_medium=plugin-description&amp;utm_campaign=1.0
5
  * Description: Protect your content, themes, plugins, and settings with <strong>realtime backup</strong> and <strong>automated security scanning</strong> from <a href="http://vaultpress.com/?utm_source=wp-admin&amp;utm_medium=plugin-description&amp;utm_campaign=1.0" rel="nofollow">VaultPress</a>. Activate, enter your registration key, and never worry again. <a href="http://vaultpress.com/help/?utm_source=wp-admin&amp;utm_medium=plugin-description&amp;utm_campaign=1.0" rel="nofollow">Need some help?</a>
6
- * Version: 2.0
7
  * Author: Automattic
8
  * Author URI: http://vaultpress.com/?utm_source=author-uri&amp;utm_medium=plugin-description&amp;utm_campaign=1.0
9
  * License: GPL2+
@@ -17,7 +17,7 @@
17
  defined( 'ABSPATH' ) || die();
18
 
19
  define( 'VAULTPRESS__MINIMUM_PHP_VERSION', '5.3.2' );
20
- define( 'VAULTPRESS__VERSION', '2.0' );
21
  define( 'VAULTPRESS__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
22
 
23
  /**
@@ -117,7 +117,2824 @@ if ( is_readable( $loader ) ) {
117
  return;
118
  }
119
 
120
- require_once VAULTPRESS__PLUGIN_DIR . 'class-vaultpress.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  $vaultpress = VaultPress::init();
122
 
123
  if ( isset( $_GET['vaultpress'] ) && $_GET['vaultpress'] ) {
3
  * Plugin Name: VaultPress
4
  * Plugin URI: http://vaultpress.com/?utm_source=plugin-uri&amp;utm_medium=plugin-description&amp;utm_campaign=1.0
5
  * Description: Protect your content, themes, plugins, and settings with <strong>realtime backup</strong> and <strong>automated security scanning</strong> from <a href="http://vaultpress.com/?utm_source=wp-admin&amp;utm_medium=plugin-description&amp;utm_campaign=1.0" rel="nofollow">VaultPress</a>. Activate, enter your registration key, and never worry again. <a href="http://vaultpress.com/help/?utm_source=wp-admin&amp;utm_medium=plugin-description&amp;utm_campaign=1.0" rel="nofollow">Need some help?</a>
6
+ * Version: 2.0.1
7
  * Author: Automattic
8
  * Author URI: http://vaultpress.com/?utm_source=author-uri&amp;utm_medium=plugin-description&amp;utm_campaign=1.0
9
  * License: GPL2+
17
  defined( 'ABSPATH' ) || die();
18
 
19
  define( 'VAULTPRESS__MINIMUM_PHP_VERSION', '5.3.2' );
20
+ define( 'VAULTPRESS__VERSION', '2.0.1' );
21
  define( 'VAULTPRESS__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
22
 
23
  /**
117
  return;
118
  }
119
 
120
+ /**
121
+ * Main VaultPress class.
122
+ */
123
+ class VaultPress {
124
+ var $option_name = 'vaultpress';
125
+ var $auto_register_option = 'vaultpress_auto_register';
126
+ var $db_version = 4;
127
+ var $plugin_version = VAULTPRESS__VERSION;
128
+
129
+ function __construct() {
130
+ register_activation_hook( __FILE__, array( $this, 'activate' ) );
131
+ register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
132
+
133
+ $this->options_blog_id = get_current_blog_id();
134
+ $options = get_option( $this->option_name );
135
+ if ( !is_array( $options ) )
136
+ $options = array();
137
+
138
+ $defaults = array(
139
+ 'db_version' => 0,
140
+ 'key' => '',
141
+ 'secret' => '',
142
+ 'connection' => false,
143
+ 'service_ips_cidr' => false
144
+ );
145
+
146
+ $this->options = wp_parse_args( $options, $defaults );
147
+ $this->reset_pings();
148
+
149
+ $this->upgrade();
150
+
151
+ $this->add_global_actions_and_filters();
152
+
153
+ if ( is_admin() ) {
154
+ $this->add_admin_actions_and_filters();
155
+ }
156
+
157
+ if ( $this->is_registered() ) {
158
+ $do_not_backup = $this->get_option( 'do_not_backup' ) || $this->get_option( 'do_not_send_backup_pings' );
159
+ if ( $do_not_backup )
160
+ $this->add_vp_required_filters();
161
+ else
162
+ $this->add_listener_actions_and_filters();
163
+ }
164
+ }
165
+
166
+ static function &init() {
167
+ static $instance = false;
168
+
169
+ if ( !$instance ) {
170
+ $instance = new VaultPress();
171
+ }
172
+
173
+ return $instance;
174
+ }
175
+
176
+ static function register( $registration_key ) {
177
+ $vp = self::init();
178
+
179
+ $nonce = wp_create_nonce( 'vp_register_' . $registration_key );
180
+ $args = array( 'registration_key' => $registration_key, 'nonce' => $nonce );
181
+ $response = $vp->contact_service( 'register', $args );
182
+
183
+ // Check for an error
184
+ if ( ! empty( $response['faultCode'] ) )
185
+ return new WP_Error( $response['faultCode'], $response['faultString'] );
186
+
187
+ // Validate result
188
+ if ( empty( $response['key'] ) || empty( $response['secret'] ) || empty( $response['nonce'] ) || $nonce != $response['nonce'] )
189
+ return new WP_Error( 1, __( 'There was a problem trying to register your VaultPress subscription.' ) );
190
+
191
+ // Store the result, force a connection test.
192
+ $vp->update_option( 'key', $response['key'] );
193
+ $vp->update_option( 'secret', $response['secret'] );
194
+ $vp->check_connection( true );
195
+
196
+ return true;
197
+ }
198
+
199
+ function activate( $network_wide ) {
200
+ $type = $network_wide ? 'network' : 'single';
201
+ $this->update_option( 'activated', $type );
202
+
203
+ // force a connection check after an activation
204
+ $this->clear_connection();
205
+
206
+ if ( get_option( 'vaultpress_auto_connect' ) ) {
207
+ $this->register_via_jetpack( true );
208
+ }
209
+ }
210
+
211
+ function deactivate() {
212
+ if ( $this->is_registered() )
213
+ $this->contact_service( 'plugin_status', array( 'vp_plugin_status' => 'deactivated' ) );
214
+ }
215
+
216
+ function upgrade() {
217
+ $current_db_version = $this->get_option( 'db_version' );
218
+
219
+ if ( $current_db_version < 1 ) {
220
+ $this->options['connection'] = get_option( 'vaultpress_connection' );
221
+ $this->options['key'] = get_option( 'vaultpress_key' );
222
+ $this->options['secret'] = get_option( 'vaultpress_secret' );
223
+ $this->options['service_ips'] = get_option( 'vaultpress_service_ips' );
224
+
225
+ // remove old options
226
+ $old_options = array(
227
+ 'vaultpress_connection',
228
+ 'vaultpress_hostname',
229
+ 'vaultpress_key',
230
+ 'vaultpress_secret',
231
+ 'vaultpress_service_ips',
232
+ 'vaultpress_timeout',
233
+ 'vp_allow_remote_execution',
234
+ 'vp_debug_request_signing',
235
+ 'vp_disable_firewall',
236
+ );
237
+
238
+ foreach ( $old_options as $option )
239
+ delete_option( $option );
240
+
241
+ $this->options['db_version'] = $this->db_version;
242
+ $this->update_options();
243
+ }
244
+
245
+ if ( $current_db_version < 2 ) {
246
+ $this->delete_option( 'timeout' );
247
+ $this->delete_option( 'disable_firewall' );
248
+ $this->update_option( 'db_version', $this->db_version );
249
+ $this->clear_connection();
250
+ }
251
+
252
+ if ( $current_db_version < 3 ) {
253
+ $this->update_firewall();
254
+ $this->update_option( 'db_version', $this->db_version );
255
+ $this->clear_connection();
256
+ }
257
+
258
+ if ( $current_db_version < 4 ) {
259
+ $this->update_firewall();
260
+ $this->update_option( 'db_version', $this->db_version );
261
+ $this->clear_connection();
262
+ }
263
+ }
264
+
265
+ function get_option( $key ) {
266
+ if ( 'hostname' == $key ) {
267
+ if ( defined( 'VAULTPRESS_HOSTNAME' ) )
268
+ return VAULTPRESS_HOSTNAME;
269
+ else
270
+ return 'vaultpress.com';
271
+ }
272
+
273
+ if ( 'timeout' == $key ) {
274
+ if ( defined( 'VAULTPRESS_TIMEOUT' ) )
275
+ return VAULTPRESS_TIMEOUT;
276
+ else
277
+ return 60;
278
+ }
279
+
280
+ if ( 'disable_firewall' == $key ) {
281
+ if ( defined( 'VAULTPRESS_DISABLE_FIREWALL' ) )
282
+ return VAULTPRESS_DISABLE_FIREWALL;
283
+ else
284
+ return false;
285
+ }
286
+
287
+ if ( ( 'key' == $key || 'secret' == $key ) && empty( $this->options[$key] ) ) {
288
+ return '';
289
+ }
290
+
291
+ // allow_forwarded_for can be overrided by config, or stored in or out of the vp option
292
+ if ( 'allow_forwarded_for' === $key ) {
293
+ if ( defined( 'ALLOW_FORWARDED_FOR' ) ) {
294
+ return ALLOW_FORWARDED_FOR;
295
+ }
296
+
297
+ $standalone_option = get_option( 'vaultpress_allow_forwarded_for' );
298
+ if ( ! empty( $standalone_option ) ) {
299
+ return $standalone_option;
300
+ }
301
+ }
302
+
303
+ if ( isset( $this->options[$key] ) )
304
+ return $this->options[$key];
305
+
306
+ return false;
307
+ }
308
+
309
+ function update_option( $key, $value ) {
310
+ if ( 'allow_forwarded_for' === $key ) {
311
+ update_option( 'vaultpress_allow_forwarded_for', $value );
312
+
313
+ if ( isset( $this->options[ $key ] ) ) {
314
+ unset( $this->options[ $key ] );
315
+ $this->update_options();
316
+ }
317
+ return;
318
+ }
319
+
320
+ $this->options[$key] = $value;
321
+ $this->update_options();
322
+ }
323
+
324
+ function delete_option( $key ) {
325
+ if ( 'allow_forwarded_for' === $key ) {
326
+ delete_option( 'vaultpress_allow_forwarded_for' );
327
+ }
328
+
329
+ unset( $this->options[$key] );
330
+ $this->update_options();
331
+ }
332
+
333
+ function update_options() {
334
+ // Avoid overwriting the VaultPress option if current blog_id has changed since reading it
335
+ if ( get_current_blog_id() !== $this->options_blog_id ) {
336
+ return;
337
+ }
338
+
339
+ update_option( $this->option_name, $this->options );
340
+ }
341
+
342
+ function admin_init() {
343
+ if ( !current_user_can( 'manage_options' ) )
344
+ return;
345
+
346
+ load_plugin_textdomain( 'vaultpress', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
347
+ }
348
+
349
+ function admin_head() {
350
+ if ( ! current_user_can( 'manage_options' ) ) {
351
+ return;
352
+ }
353
+
354
+ // Array of hooks where we want to hook our notices.
355
+ $notice_hooks = array( 'user_admin_notices' );
356
+
357
+ /*
358
+ * In the VaultPress dashboard, move the notices.
359
+ */
360
+ $screen = get_current_screen();
361
+ if (
362
+ ! is_null( $screen )
363
+ && in_array(
364
+ $screen->id,
365
+ array( 'jetpack_page_vaultpress', 'toplevel_page_vaultpress' ),
366
+ true
367
+ )
368
+ ) {
369
+ $notice_hooks[] = 'vaultpress_notices';
370
+ } else {
371
+ $notice_hooks[] = 'admin_notices';
372
+ }
373
+
374
+ if ( $activated = $this->get_option( 'activated' ) ) {
375
+ if ( 'network' == $activated ) {
376
+ add_action( 'network_admin_notices', array( $this, 'activated_notice' ) );
377
+ } else {
378
+ foreach ( $notice_hooks as $filter ) {
379
+ add_action( $filter, array( $this, 'activated_notice' ) );
380
+ }
381
+ }
382
+ }
383
+
384
+ // ask the user to connect their site w/ VP
385
+ if ( !$this->is_registered() ) {
386
+ foreach ( $notice_hooks as $filter ) {
387
+ add_action( $filter, array( $this, 'connect_notice' ) );
388
+ }
389
+
390
+ // if we have an error make sure to let the user know about it
391
+ } else {
392
+ $error_code = $this->get_option( 'connection_error_code' );
393
+ if ( ! empty( $error_code ) ) {
394
+ foreach ( $notice_hooks as $filter ) {
395
+ add_action( $filter, array( $this, 'error_notice' ) );
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ function admin_menu() {
402
+ // if Jetpack is loaded then we need to wait for that menu to be added
403
+ if ( class_exists( 'Jetpack' ) )
404
+ add_action( 'jetpack_admin_menu', array( $this, 'load_menu' ) );
405
+ else
406
+ $this->load_menu();
407
+ }
408
+
409
+ function load_menu() {
410
+ if ( class_exists( 'Jetpack' ) ) {
411
+ $hook = add_submenu_page( 'jetpack', 'VaultPress', 'VaultPress', 'manage_options', 'vaultpress', array( $this, 'ui' ) );
412
+ } else {
413
+ $hook = add_menu_page( 'VaultPress', 'VaultPress', 'manage_options', 'vaultpress', array( $this, 'ui' ), 'div' );
414
+ }
415
+
416
+ add_action( "load-$hook", array( $this, 'ui_load' ) );
417
+ add_action( 'admin_print_styles', array( $this, 'styles' ) );
418
+ }
419
+
420
+ function styles() {
421
+ if ( !current_user_can( 'manage_options' ) || !is_admin() )
422
+ return;
423
+
424
+ wp_enqueue_style( 'vaultpress-nav', plugins_url( '/nav-styles.css', __FILE__ ), false, date( 'Ymd' ) );
425
+
426
+ if ( isset( $_GET['page'] ) && 'vaultpress' == $_GET['page'] )
427
+ wp_enqueue_style( 'vaultpress', plugins_url( '/styles.css', __FILE__ ), false, date( 'Ymd' ) );
428
+ }
429
+
430
+ // display a security threat notice if one exists
431
+ function toolbar( $wp_admin_bar ) {
432
+ global $wp_version;
433
+
434
+ // these new toolbar functions were introduced in 3.3
435
+ // http://codex.wordpress.org/Function_Reference/add_node
436
+ if ( version_compare( $wp_version, '3.3', '<') )
437
+ return;
438
+
439
+ if ( !current_user_can( 'manage_options' ) )
440
+ return;
441
+
442
+ $messages = $this->get_messages();
443
+ if ( !empty( $messages['security_notice_count'] ) ) {
444
+ $count = (int)$messages['security_notice_count'];
445
+ if ( $count > 0 ) {
446
+ $count = number_format( $count, 0 );
447
+ $wp_admin_bar->add_node( array(
448
+ 'id' => 'vp-notice',
449
+ 'title' => '<span class="ab-icon"></span>' .
450
+ sprintf( _n( '%s Security Threat', '%s Security Threats', $count , 'vaultpress'), $count ),
451
+ 'parent' => 'top-secondary',
452
+ 'href' => sprintf( 'https://dashboard.vaultpress.com/%d/security/', $messages['site_id'] ),
453
+ 'meta' => array(
454
+ 'title' => __( 'Visit VaultPress Security' , 'vaultpress'),
455
+ 'onclick' => 'window.open( this.href ); return false;',
456
+ 'class' => 'error'
457
+ ),
458
+ ) );
459
+ }
460
+ }
461
+ }
462
+
463
+ // get any messages from the VP servers
464
+ function get_messages( $force_reload = false ) {
465
+ $last_contact = $this->get_option( 'messages_last_contact' );
466
+
467
+ // only run the messages check every 30 minutes
468
+ if ( ( time() - (int)$last_contact ) > 1800 || $force_reload ) {
469
+ $messages = base64_decode( $this->contact_service( 'messages', array() ) );
470
+ $messages = unserialize( $messages );
471
+ $this->update_option( 'messages_last_contact', time() );
472
+ $this->update_option( 'messages', $messages );
473
+ } else {
474
+ $messages = $this->get_option( 'messages' );
475
+ }
476
+
477
+ return $messages;
478
+ }
479
+
480
+ function server_url() {
481
+ if ( !isset( $this->_server_url ) ) {
482
+ $scheme = is_ssl() ? 'https' : 'http';
483
+ $this->_server_url = sprintf( '%s://%s/', $scheme, $this->get_option( 'hostname' ) );
484
+ }
485
+
486
+ return $this->_server_url;
487
+ }
488
+
489
+ // show message if plugin is activated but not connected to VaultPress
490
+ function connect_notice() {
491
+ if ( isset( $_GET['page'] ) && 'vaultpress' == $_GET['page'] )
492
+ return;
493
+
494
+ $message = sprintf(
495
+ __( 'You must enter your registration key before VaultPress can back up and secure your site. <a href="%1$s">Register&nbsp;VaultPress</a>', 'vaultpress' ),
496
+ admin_url( 'admin.php?page=vaultpress' )
497
+ );
498
+ $this->ui_message( $message, 'notice', __( 'VaultPress needs your attention!', 'vaultpress' ) );
499
+ }
500
+
501
+ // show message after activation
502
+ function activated_notice() {
503
+ if ( 'network' == $this->get_option( 'activated' ) ) {
504
+ $message = sprintf(
505
+ __( 'Each site will need to be registered with VaultPress separately. You can purchase new keys from your <a href="%1$s">VaultPress&nbsp;Dashboard</a>.', 'vaultpress' ),
506
+ 'https://dashboard.vaultpress.com/'
507
+ );
508
+ $this->ui_message( $message, 'activated', __( 'VaultPress has been activated across your network!', 'vaultpress' ) );
509
+
510
+ // key and secret already exist in db
511
+ } elseif ( $this->is_registered() ) {
512
+ if ( $this->check_connection() ) {
513
+ }
514
+ }
515
+
516
+ $this->delete_option( 'activated' );
517
+ }
518
+
519
+ function error_notice() {
520
+ $error_message = $this->get_option( 'connection_error_message' );
521
+
522
+ // link to the VaultPress page if we're not already there
523
+ if ( !isset( $_GET['page'] ) || 'vaultpress' != $_GET['page'] ) {
524
+ $error_message .= ' ' . sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=vaultpress' ), __( 'Visit&nbsp;the&nbsp;VaultPress&nbsp;page' , 'vaultpress') );
525
+ }
526
+
527
+ $screen = get_current_screen();
528
+ if ( !in_array( $screen->id, array( 'about', 'about-user', 'about-network' ) ) && !empty( $error_message ) ) {
529
+ $this->ui_message( $error_message, 'error' );
530
+ }
531
+ }
532
+
533
+ /**
534
+ * Adds the main wrappers and the header, and defers controls to ui_render to decide which view to render.
535
+ */
536
+ function ui() {
537
+ $ui_state = $this->ui_render();
538
+ ?>
539
+ <div id="jp-plugin-container">
540
+ <?php $this->ui_masthead( $ui_state[ 'dashboard_link' ] ); ?>
541
+ <div class="vp-wrap">
542
+ <?php
543
+ /**
544
+ * Allow the display of custom notices.
545
+ *
546
+ * @since 2.0.0
547
+ */
548
+ do_action( 'vaultpress_notices' );
549
+ ?>
550
+ <?php echo $ui_state[ 'ui' ]; // This content is sanitized when it's produced. ?>
551
+ </div>
552
+ <?php $this->ui_footer(); ?>
553
+ </div>
554
+ <?php
555
+ }
556
+
557
+ /**
558
+ * Decides which UI view to render and executes it.
559
+ *
560
+ * @return array $args {
561
+ * An array of options to render the dashboard.
562
+ *
563
+ * @type string $ui Dashboard markup.
564
+ * @type string $dashboard_link Whether to show the link to the VaultPress dashboard.
565
+ * }
566
+ */
567
+ function ui_render() {
568
+ ob_start();
569
+
570
+ if ( $this->is_localhost() ) {
571
+ $this->update_option( 'connection', time() );
572
+ $this->update_option( 'connection_error_code', 'error_localhost' );
573
+ $this->update_option( 'connection_error_message', 'Hostnames such as localhost or 127.0.0.1 can not be reached by vaultpress.com and will not work with the service. Sites must be publicly accessible in order to work with VaultPress.' );
574
+ $this->error_notice();
575
+ return array( 'ui' => ob_get_clean(), 'dashboard_link' => false );
576
+ }
577
+
578
+ if ( ! empty( $_GET[ 'error' ] ) ) {
579
+ $this->error_notice();
580
+ $this->clear_connection();
581
+ }
582
+
583
+ if ( ! $this->is_registered() ) {
584
+ $this->ui_register();
585
+ return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
586
+ }
587
+
588
+ $status = $this->contact_service( 'status' );
589
+ if ( ! $status ) {
590
+ $error_code = $this->get_option( 'connection_error_code' );
591
+ if ( 0 == $error_code ) {
592
+ $this->ui_fatal_error();
593
+ } else {
594
+ $this->ui_register();
595
+ }
596
+ return array( 'ui' => ob_get_clean(), 'dashboard_link' => 0 != $error_code );
597
+ }
598
+
599
+ $ticker = $this->contact_service( 'ticker' );
600
+ if ( is_array( $ticker ) && isset( $ticker[ 'faultCode' ] ) ) {
601
+ $this->error_notice();
602
+ $this->ui_register();
603
+ return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
604
+ }
605
+
606
+ $this->ui_main();
607
+ return array( 'ui' => ob_get_clean(), 'dashboard_link' => true );
608
+ }
609
+
610
+ function ui_load() {
611
+ if ( ! current_user_can( 'manage_options' ) ) {
612
+ return;
613
+ }
614
+
615
+ if ( isset( $_POST['action'] ) && 'delete-vp-settings' == $_POST['action'] ) {
616
+ check_admin_referer( 'delete_vp_settings' );
617
+
618
+ $ai_ping_queue_size = $this->ai_ping_queue_size();
619
+ if ( ! empty( $ai_ping_queue_size->option_count ) && $ai_ping_queue_size->option_count > 1 ) {
620
+ $this->ai_ping_queue_delete();
621
+ }
622
+
623
+ delete_option( $this->option_name );
624
+ delete_option( 'vaultpress_service_ips_external_cidr' );
625
+ delete_option( '_vp_signatures' );
626
+ delete_option( '_vp_config_option_name_ignore' );
627
+ delete_option( '_vp_config_post_meta_name_ignore' );
628
+ delete_option( '_vp_config_should_ignore_files' );
629
+ delete_option( '_vp_current_scan' );
630
+ delete_option( 'vaultpress_auto_register' );
631
+
632
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&delete-vp-settings=1' ) );
633
+ exit();
634
+ }
635
+
636
+ // run code that might be updating the registration key
637
+ if ( isset( $_POST['action'] ) && 'register' == $_POST['action'] ) {
638
+ check_admin_referer( 'vaultpress_register' );
639
+
640
+ // reset the connection info so messages don't cross
641
+ $this->clear_connection();
642
+
643
+ // if registering via Jetpack, get a key...
644
+ if ( isset( $_POST['key_source'] ) && 'jetpack' === $_POST['key_source'] ) {
645
+ $registration_key = $this->get_key_via_jetpack();
646
+ if ( is_wp_error( $registration_key ) ) {
647
+ $this->update_option( 'connection_error_code', -2 );
648
+ $this->update_option(
649
+ 'connection_error_message',
650
+ sprintf( __('<strong>Failed to register VaultPress via Jetpack</strong>: %s. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ),
651
+ esc_html( $registration_key->get_error_message() ), 'http://vaultpress.com/contact/' )
652
+ );
653
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
654
+ exit();
655
+ }
656
+ } else {
657
+ $registration_key = trim( $_POST[ 'registration_key' ] );
658
+ }
659
+
660
+ if ( empty( $registration_key ) ) {
661
+ $this->update_option( 'connection_error_code', 1 );
662
+ $this->update_option(
663
+ 'connection_error_message',
664
+ sprintf(
665
+ __( '<strong>That\'s not a valid registration key.</strong> Head over to the <a href="%1$s" title="Sign in to your VaultPress Dashboard">VaultPress&nbsp;Dashboard</a> to find your key.', 'vaultpress' ),
666
+ 'https://dashboard.vaultpress.com/'
667
+ )
668
+ );
669
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
670
+ exit();
671
+ }
672
+
673
+ // try to register the plugin
674
+ $nonce = wp_create_nonce( 'vp_register_' . $registration_key );
675
+ $args = array( 'registration_key' => $registration_key, 'nonce' => $nonce );
676
+ $response = $this->contact_service( 'register', $args );
677
+
678
+ // we received an error from the VaultPress servers
679
+ if ( !empty( $response['faultCode'] ) ) {
680
+ $this->update_option( 'connection_error_code', $response['faultCode'] );
681
+ $this->update_option( 'connection_error_message', $response['faultString'] );
682
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
683
+ exit();
684
+ }
685
+
686
+ // make sure the returned data looks valid
687
+ if ( empty( $response['key'] ) || empty( $response['secret'] ) || empty( $response['nonce'] ) || $nonce != $response['nonce'] ) {
688
+ $this->update_option( 'connection_error_code', 1 );
689
+ $this->update_option( 'connection_error_message', sprintf( __( 'There was a problem trying to register your subscription. Please try again. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
690
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
691
+ exit();
692
+ }
693
+
694
+ // need to update these values in the db so the servers can try connecting to the plugin
695
+ $this->update_option( 'key', $response['key'] );
696
+ $this->update_option( 'secret', $response['secret'] );
697
+ if ( $this->check_connection( true ) ) {
698
+ wp_redirect( admin_url( 'admin.php?page=vaultpress' ) );
699
+ exit();
700
+ }
701
+
702
+ // reset the key and secret
703
+ $this->update_option( 'key', '' );
704
+ $this->update_option( 'secret', '' );
705
+ wp_redirect( admin_url( 'admin.php?page=vaultpress&error=true' ) );
706
+ exit();
707
+ }
708
+ }
709
+
710
+ function ui_register() {
711
+ ?>
712
+ <div class="vp-notice__wide">
713
+ <div class="dops-card">
714
+ <img src="<?php echo esc_url( plugins_url( 'images/security.svg', __FILE__ ) ); ?>" alt="VaultPress">
715
+ <h2><?php _e( 'The VaultPress plugin requires a subscription.', 'vaultpress' ); ?></h2>
716
+ <p><?php _e( 'Get realtime backups, automated security scanning, and support from WordPress&nbsp;experts.', 'vaultpress' ); ?></p>
717
+ <a class="dops-button is-primary" href="https://vaultpress.com/plugin/?utm_source=plugin-unregistered&amp;utm_medium=view-plans-and-pricing&amp;utm_campaign=1.0-plugin" target="_blank" rel="noopener noreferrer"><?php _e( 'View plans and pricing', 'vaultpress' ); ?></a>
718
+ </div>
719
+ </div>
720
+
721
+ <div class="jp-dash-section-header">
722
+ <div class="jp-dash-section-header__label">
723
+ <h2 class="jp-dash-section-header__name">
724
+ <?php esc_html_e( 'Management', 'vaultpress' ); ?>
725
+ </h2>
726
+ </div>
727
+ </div>
728
+
729
+ <div class="vp-row">
730
+ <div class="vp-col">
731
+ <div class="dops-card dops-section-header is-compact">
732
+ <?php esc_html_e( 'Registration key', 'vaultpress' ) ?>
733
+ </div>
734
+ <div class="dops-card">
735
+ <form method="post" action="">
736
+ <fieldset>
737
+ <p>
738
+ <?php esc_html_e( 'Paste your registration key&nbsp;below:', 'vaultpress' ); ?>
739
+ </p>
740
+ <p>
741
+ <textarea class="dops-textarea" placeholder="<?php esc_attr_e( __( 'Enter your key here...', 'vaultpress' ) ); ?>" name="registration_key"></textarea>
742
+ </p>
743
+ <button class="dops-button is-compact"><?php _e( 'Register ', 'vaultpress' ); ?></button>
744
+ <input type="hidden" name="action" value="register" />
745
+ <?php wp_nonce_field( 'vaultpress_register' ); ?>
746
+ </fieldset>
747
+ </form>
748
+ </div>
749
+ </div>
750
+ <div class="vp-col">
751
+ <?php $this->ui_delete_vp_settings_button(); ?>
752
+ </div>
753
+ </div>
754
+ <?php
755
+ }
756
+
757
+ /**
758
+ * Renders the top header.
759
+ *
760
+ * @param bool $show_nav Whether to show navigation.
761
+ */
762
+ function ui_masthead( $show_nav = true ) {
763
+ ?>
764
+ <div class="jp-masthead">
765
+ <div class="jp-masthead__inside-container">
766
+ <div class="jp-masthead__logo-container">
767
+ <a class="jp-masthead__logo-link" href="https://vaultpress.com">
768
+ <img src="<?php echo esc_url( plugins_url( 'images/vaultpress.svg', __FILE__ ) ); ?>" alt="VaultPress">
769
+ </a>
770
+ </div>
771
+ <?php if ( $show_nav ) : ?>
772
+ <div class="jp-masthead__nav">
773
+ <div class="dops-button-group">
774
+ <a href="https://dashboard.vaultpress.com" class="dops-button is-compact" target="_blank" rel="noopener noreferrer">
775
+ <?php _e( 'Visit Dashboard', 'vaultpress' ); ?>
776
+ </a>
777
+ </div>
778
+ </div>
779
+ <?php endif; ?>
780
+ </div>
781
+ </div>
782
+ <?php
783
+ }
784
+
785
+ /**
786
+ * Renders the footer.
787
+ */
788
+ function ui_footer() {
789
+ ?>
790
+ <div class="jp-footer">
791
+ <div class="jp-footer__a8c-attr-container">
792
+ <svg role="img" class="jp-footer__a8c-attr" x="0" y="0" viewBox="0 0 935 38.2" enable-background="new 0 0 935 38.2" aria-labelledby="a8c-svg-title"><title id="a8c-svg-title">An Automattic Airline</title>
793
+ <path d="M317.1 38.2c-12.6 0-20.7-9.1-20.7-18.5v-1.2c0-9.6 8.2-18.5 20.7-18.5 12.6 0 20.8 8.9 20.8 18.5v1.2C337.9 29.1 329.7 38.2 317.1 38.2zM331.2 18.6c0-6.9-5-13-14.1-13s-14 6.1-14 13v0.9c0 6.9 5 13.1 14 13.1s14.1-6.2 14.1-13.1V18.6zM175 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7L157 1.3h5.5L182 36.8H175zM159.7 8.2L152 23.1h15.7L159.7 8.2zM212.4 38.2c-12.7 0-18.7-6.9-18.7-16.2V1.3h6.6v20.9c0 6.6 4.3 10.5 12.5 10.5 8.4 0 11.9-3.9 11.9-10.5V1.3h6.7V22C231.4 30.8 225.8 38.2 212.4 38.2zM268.6 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H268.6zM397.3 36.8V8.7l-1.8 3.1 -14.9 25h-3.3l-14.7-25 -1.8-3.1v28.1h-6.5V1.3h9.2l14 24.4 1.7 3 1.7-3 13.9-24.4h9.1v35.5H397.3zM454.4 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7l19.2-35.5h5.5l19.5 35.5H454.4zM439.1 8.2l-7.7 14.9h15.7L439.1 8.2zM488.4 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H488.4zM537.3 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H537.3zM569.3 36.8V4.6c2.7 0 3.7-1.4 3.7-3.4h2.8v35.5L569.3 36.8 569.3 36.8zM628 11.3c-3.2-2.9-7.9-5.7-14.2-5.7 -9.5 0-14.8 6.5-14.8 13.3v0.7c0 6.7 5.4 13 15.3 13 5.9 0 10.8-2.8 13.9-5.7l4 4.2c-3.9 3.8-10.5 7.1-18.3 7.1 -13.4 0-21.6-8.7-21.6-18.3v-1.2c0-9.6 8.9-18.7 21.9-18.7 7.5 0 14.3 3.1 18 7.1L628 11.3zM321.5 12.4c1.2 0.8 1.5 2.4 0.8 3.6l-6.1 9.4c-0.8 1.2-2.4 1.6-3.6 0.8l0 0c-1.2-0.8-1.5-2.4-0.8-3.6l6.1-9.4C318.7 11.9 320.3 11.6 321.5 12.4L321.5 12.4z"></path>
794
+ <path d="M37.5 36.7l-4.7-8.9H11.7l-4.6 8.9H0L19.4 0.8H25l19.7 35.9H37.5zM22 7.8l-7.8 15.1h15.9L22 7.8zM82.8 36.7l-23.3-24 -2.3-2.5v26.6h-6.7v-36H57l22.6 24 2.3 2.6V0.8h6.7v35.9H82.8z"></path>
795
+ <path d="M719.9 37l-4.8-8.9H694l-4.6 8.9h-7.1l19.5-36h5.6l19.8 36H719.9zM704.4 8l-7.8 15.1h15.9L704.4 8zM733 37V1h6.8v36H733zM781 37c-1.8 0-2.6-2.5-2.9-5.8l-0.2-3.7c-0.2-3.6-1.7-5.1-8.4-5.1h-12.8V37H750V1h19.6c10.8 0 15.7 4.3 15.7 9.9 0 3.9-2 7.7-9 9 7 0.5 8.5 3.7 8.6 7.9l0.1 3c0.1 2.5 0.5 4.3 2.2 6.1V37H781zM778.5 11.8c0-2.6-2.1-5.1-7.9-5.1h-13.8v10.8h14.4c5 0 7.3-2.4 7.3-5.2V11.8zM794.8 37V1h6.8v30.4h28.2V37H794.8zM836.7 37V1h6.8v36H836.7zM886.2 37l-23.4-24.1 -2.3-2.5V37h-6.8V1h6.5l22.7 24.1 2.3 2.6V1h6.8v36H886.2zM902.3 37V1H935v5.6h-26v9.2h20v5.5h-20v10.1h26V37H902.3z"></path>
796
+ </svg>
797
+ </div>
798
+ <ul class="jp-footer__links">
799
+ <li class="jp-footer__link-item">
800
+ <a href="https://vaultpress.com" class="jp-footer__link" title="<?php esc_attr_e( 'VaultPress version', 'vaultpress' ) ?>" target="_blank" rel="noopener noreferrer">
801
+ <?php printf( 'VaultPress %s', $this->plugin_version ); ?>
802
+ </a>
803
+ </li>
804
+ <li class="jp-footer__link-item">
805
+ <a href="https://wordpress.com/tos/" class="jp-footer__link" title="<?php esc_attr_e( 'Terms of service', 'vaultpress' ) ?>" target="_blank" rel="noopener noreferrer">
806
+ <?php esc_html_e( 'Terms', 'vaultpress' ); ?>
807
+ </a>
808
+ </li>
809
+ </ul>
810
+ <div class="jp-power">
811
+ <a
812
+ href="<?php echo class_exists( 'Jetpack_Admin_Page' ) ? esc_url( admin_url( 'admin.php?page=jetpack' ) ) : 'https://jetpack.com' ?>"
813
+ class="jp-power__text-link"
814
+ target="_blank"
815
+ rel="noopener noreferrer"
816
+ >
817
+ <span class="jp-power__text"><?php esc_html_e( 'Powered by', 'vaultpress') ?></span> <?php echo $this->ui_logo(); ?>
818
+ </a>
819
+ </div>
820
+ </div>
821
+ <?php
822
+ }
823
+
824
+ function ui_main() {
825
+ $response = base64_decode( $this->contact_service( 'plugin_ui' ) );
826
+ echo $response;
827
+ $this->ui_delete_vp_settings_button();
828
+ }
829
+
830
+ function ui_fatal_error() {
831
+ $this->render_notice(
832
+ sprintf(
833
+ '<strong>' . __( 'We can\'t connect to %1$s.', 'vaultpress' ) . '</strong><br/>' .
834
+ __( 'Please make sure that your website is accessible via the Internet. Please contact the VaultPress support if you still have issues.' ),
835
+ esc_html( $this->get_option( 'hostname' ) )
836
+ ),
837
+ 'is-warning',
838
+ array(
839
+ 'label' => __( 'Contact support' ),
840
+ 'url' => 'https://vaultpress.com/contact/',
841
+ )
842
+ );
843
+ }
844
+
845
+ function ui_message( $message, $type = 'notice', $heading = '' ) {
846
+ $level = 'is-warning';
847
+ if ( empty( $heading ) ) {
848
+ switch ( $type ) {
849
+ case 'error':
850
+ $level = 'is-error';
851
+ $heading = __( 'Oops... there seems to be a problem.', 'vaultpress' );
852
+ break;
853
+
854
+ case 'success':
855
+ $level = 'is-success';
856
+ $heading = __( 'Yay! Things look good.', 'vaultpress' );
857
+ break;
858
+
859
+ default:
860
+ $heading = __( 'VaultPress needs your attention!', 'vaultpress' );
861
+ break;
862
+ }
863
+ }
864
+
865
+ $classes = in_array( get_current_screen()->parent_base, array( 'jetpack', 'vaultpress' ), true )
866
+ ? ''
867
+ : "notice notice-$type";
868
+
869
+ $this->render_notice(
870
+ "<strong>$heading</strong><br/>$message",
871
+ $level,
872
+ array(),
873
+ $classes
874
+ );
875
+ }
876
+
877
+ /**
878
+ * Renders a notice. Can have
879
+ *
880
+ * @param string $content Notice main content.
881
+ * @param string $level Can be is-info, is-warning, is-error. By default, it's is-info.
882
+ * @param array $action {
883
+ * Arguments to display a linked action button in the notice.
884
+ *
885
+ * @type string $label The action button label.
886
+ * @type string $url The action button link.
887
+ * }
888
+ * @param string $classes This is added as a CSS class to the root node. Useful to pass WP core classes for notices.
889
+ */
890
+ function render_notice( $content, $level = 'is-info', $action = array(), $classes = '' ) {
891
+ $allowed_html = array(
892
+ 'a' => array( 'href' => true, 'target' => 'blank', 'rel' => 'noopener noreferrer' ),
893
+ 'br' => true,
894
+ 'strong' => true,
895
+ );
896
+ ?>
897
+ <div class="dops-notice vp-notice <?php echo esc_attr( "$level $classes" ) ?>">
898
+ <span class="dops-notice__icon-wrapper">
899
+ <svg class="gridicon gridicons-info dops-notice__icon" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
900
+ <path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" />
901
+ </svg>
902
+ </span>
903
+ <span class="dops-notice__content">
904
+ <span class="dops-notice__text"><?php echo wp_kses( $content, $allowed_html ) ?></span>
905
+ </span>
906
+ <?php if ( ! empty( $action ) ) : ?>
907
+ <a class="dops-notice__action" href="<?php echo esc_attr( $action['url'] ) ?>" target="_blank" rel="noopener noreferrer">
908
+ <span><?php echo esc_html( $action['label'] ) ?></span>
909
+ </a>
910
+ <?php endif; ?>
911
+ </div>
912
+ <?php
913
+ }
914
+
915
+ function ui_delete_vp_settings_button() {
916
+ ?>
917
+ <div class="dops-card dops-section-header is-compact">
918
+ <?php _e( 'Settings reset', 'vaultpress' ); ?>
919
+ </div>
920
+ <?php
921
+ if ( isset( $_GET['delete-vp-settings'] ) && 1 == (int) $_GET['delete-vp-settings'] ) {
922
+ ?>
923
+ <div class="dops-card">
924
+ <p><?php _e( 'All VaultPress settings have been deleted.', 'vaultpress' ); ?></p>
925
+ </div>
926
+ <?php
927
+ } else {
928
+ ?>
929
+ <div class="dops-card">
930
+ <p><?php _e( 'Click this button to reset all VaultPress options in the database.', 'vaultpress' ); ?></p>
931
+ <p><strong><?php esc_html_e( 'Warning: this process is irreversible.', 'vaultpress' ) ?></strong></p>
932
+ <form
933
+ onsubmit="return confirm( '<?php esc_html_e( 'Do you really want to reset all options?', 'vaultpress' ) ?>' );"
934
+ method="post"
935
+ action="">
936
+ <button class="dops-button is-scary is-compact"><?php esc_html_e( 'Delete all settings', 'vaultpress' ); ?></button>
937
+ <input type="hidden" name="action" value="delete-vp-settings"/>
938
+ <?php wp_nonce_field( 'delete_vp_settings' ); ?>
939
+ </form>
940
+ </div>
941
+ <?php
942
+ }
943
+ }
944
+
945
+ /**
946
+ * Render the Jetpack logo
947
+ */
948
+ function ui_logo() {
949
+ if ( ! class_exists( 'Jetpack_Logo' ) ) {
950
+ require_once VAULTPRESS__PLUGIN_DIR . 'class-jetpack-logo.php';
951
+ $jetpack_logo = new Jetpack_Logo();
952
+ }
953
+
954
+ return $jetpack_logo->output();
955
+ }
956
+
957
+ function get_config( $key ) {
958
+ $val = get_option( $key );
959
+ if ( $val )
960
+ return $val;
961
+ switch( $key ) {
962
+ case '_vp_config_option_name_ignore':
963
+ $val = $this->get_option_name_ignore( true );
964
+ update_option( '_vp_config_option_name_ignore', $val );
965
+ break;
966
+ case '_vp_config_post_meta_name_ignore':
967
+ $val = $this->get_post_meta_name_ignore( true );
968
+ update_option( '_vp_config_post_meta_name_ignore', $val );
969
+ break;
970
+ case '_vp_config_should_ignore_files':
971
+ $val = $this->get_should_ignore_files( true );
972
+ update_option( '_vp_config_should_ignore_files', $val );
973
+ break;
974
+ }
975
+ return $val;
976
+ }
977
+
978
+ // Option name patterns to ignore
979
+ function get_option_name_ignore( $return_defaults = false ) {
980
+ $defaults = array(
981
+ 'vaultpress',
982
+ 'cron',
983
+ 'wpsupercache_gc_time',
984
+ 'rewrite_rules',
985
+ 'akismet_spam_count',
986
+ '/_transient_/',
987
+ '/^_vp_/',
988
+ );
989
+ if ( $return_defaults )
990
+ return $defaults;
991
+ $ignore_names = $this->get_config( '_vp_config_option_name_ignore' );
992
+ return array_unique( array_merge( $defaults, $ignore_names ) );
993
+ }
994
+
995
+ // post meta name patterns to ignore
996
+ function get_post_meta_name_ignore( $return_defaults = false ) {
997
+ $defaults = array(
998
+ 'pvc_views'
999
+ );
1000
+ if ( $return_defaults )
1001
+ return $defaults;
1002
+ $ignore_names = $this->get_config( '_vp_config_post_meta_name_ignore' );
1003
+ return array_unique( array_merge( $defaults, $ignore_names ) );
1004
+ }
1005
+
1006
+ // file name patterns to ignore
1007
+ function get_should_ignore_files( $return_defaults = false ) {
1008
+ $defaults = array();
1009
+ if ( $return_defaults )
1010
+ return $defaults;
1011
+ $ignore_names = (array) $this->get_config( '_vp_config_should_ignore_files' );
1012
+ return array_unique( array_merge( $defaults, $ignore_names ) );
1013
+ }
1014
+
1015
+ ###
1016
+ ### Section: Backup Notification Hooks
1017
+ ###
1018
+
1019
+ // Handle Handle Notifying VaultPress of Options Activity At this point the options table has already been modified
1020
+ //
1021
+ // Note: we handle deleted, instead of delete because VaultPress backs up options by name (which are unique,) that
1022
+ // means that we do not need to resolve an id like we would for, say, a post.
1023
+ function option_handler( $option_name ) {
1024
+ global $wpdb;
1025
+ // Step 1 -- exclusionary rules, don't send these options to vaultpress, because they
1026
+ // either change constantly and/or are inconsequential to the blog itself and/or they
1027
+ // are specific to the VaultPress plugin process and we want to avoid recursion
1028
+ $should_ping = true;
1029
+ $ignore_names = $this->get_option_name_ignore();
1030
+ foreach( (array)$ignore_names as $val ) {
1031
+ if ( $val{0} == '/' ) {
1032
+ if ( preg_match( $val, $option_name ) )
1033
+ $should_ping = false;
1034
+ } else {
1035
+ if ( $val == $option_name )
1036
+ $should_ping = false;
1037
+ }
1038
+ if ( !$should_ping )
1039
+ break;
1040
+ }
1041
+ if ( $should_ping )
1042
+ $this->add_ping( 'db', array( 'option' => $option_name ) );
1043
+
1044
+ // Step 2 -- If WordPress is about to kick off a some "cron" action, we need to
1045
+ // flush vaultpress, because the "remote" cron threads done via http fetch will
1046
+ // be happening completely inside the window of this thread. That thread will
1047
+ // be expecting touched and accounted for tables
1048
+ if ( $option_name == '_transient_doing_cron' )
1049
+ $this->do_pings();
1050
+
1051
+ return $option_name;
1052
+ }
1053
+
1054
+ // Handle Notifying VaultPress of Comment Activity
1055
+ function comment_action_handler( $comment_id ) {
1056
+ if ( !is_array( $comment_id ) ) {
1057
+ if ( wp_get_comment_status( $comment_id ) != 'spam' )
1058
+ $this->add_ping( 'db', array( 'comment' => $comment_id ) );
1059
+ } else {
1060
+ foreach ( $comment_id as $id ) {
1061
+ if ( wp_get_comment_status( $comment_id ) != 'spam' )
1062
+ $this->add_ping( 'db', array( 'comment' => $id) );
1063
+ }
1064
+ }
1065
+ }
1066
+
1067
+ // Handle Notifying VaultPress of Theme Switches
1068
+ function theme_action_handler( $theme ) {
1069
+ $this->add_ping( 'themes', array( 'theme' => get_option( 'stylesheet' ) ) );
1070
+ }
1071
+
1072
+ // Handle Notifying VaultPress of Upload Activity
1073
+ function upload_handler( $file ) {
1074
+ $this->add_ping( 'uploads', array( 'upload' => str_replace( $this->resolve_upload_path(), '', $file['file'] ) ) );
1075
+ return $file;
1076
+ }
1077
+
1078
+ // Handle Notifying VaultPress of Plugin Activation/Deactivation
1079
+ function plugin_action_handler( $plugin='' ) {
1080
+ $this->add_ping( 'plugins', array( 'name' => $plugin ) );
1081
+ }
1082
+
1083
+ // Handle Notifying VaultPress of User Edits
1084
+ function userid_action_handler( $user_or_id ) {
1085
+ if ( is_object($user_or_id) )
1086
+ $userid = intval( $user_or_id->ID );
1087
+ else
1088
+ $userid = intval( $user_or_id );
1089
+ if ( !$userid )
1090
+ return;
1091
+ $this->add_ping( 'db', array( 'user' => $userid ) );
1092
+ }
1093
+
1094
+ // Handle Notifying VaultPress of term changes
1095
+ function term_handler( $term_id, $tt_id=null ) {
1096
+ $this->add_ping( 'db', array( 'term' => $term_id ) );
1097
+ if ( $tt_id )
1098
+ $this->term_taxonomy_handler( $tt_id );
1099
+ }
1100
+
1101
+ // Handle Notifying VaultPress of term_taxonomy changes
1102
+ function term_taxonomy_handler( $tt_id ) {
1103
+ $this->add_ping( 'db', array( 'term_taxonomy' => $tt_id ) );
1104
+ }
1105
+ // add(ed)_term_taxonomy handled via the created_term hook, the term_taxonomy_handler is called by the term_handler
1106
+
1107
+ // Handle Notifying VaultPress of term_taxonomy changes
1108
+ function term_taxonomies_handler( $tt_ids ) {
1109
+ foreach( (array)$tt_ids as $tt_id ) {
1110
+ $this->term_taxonomy_handler( $tt_id );
1111
+ }
1112
+ }
1113
+
1114
+ // Handle Notifying VaultPress of term_relationship changes
1115
+ function term_relationship_handler( $object_id, $term_id ) {
1116
+ $this->add_ping( 'db', array( 'term_relationship' => array( 'object_id' => $object_id, 'term_taxonomy_id' => $term_id ) ) );
1117
+ }
1118
+
1119
+ // Handle Notifying VaultPress of term_relationship changes
1120
+ function term_relationships_handler( $object_id, $term_ids ) {
1121
+ foreach ( (array)$term_ids as $term_id ) {
1122
+ $this->term_relationship_handler( $object_id, $term_id );
1123
+ }
1124
+ }
1125
+
1126
+ // Handle Notifying VaultPress of term_relationship changes
1127
+ function set_object_terms_handler( $object_id, $terms, $tt_ids ) {
1128
+ $this->term_relationships_handler( $object_id, $tt_ids );
1129
+ }
1130
+
1131
+ // Handle Notifying VaultPress of UserMeta changes
1132
+ function usermeta_action_handler( $umeta_id, $user_id, $meta_key, $meta_value='' ) {
1133
+ $this->add_ping( 'db', array( 'usermeta' => $umeta_id ) );
1134
+ }
1135
+
1136
+ // Handle Notifying VaultPress of Post Changes
1137
+ function post_action_handler($post_id) {
1138
+ if ( current_filter() == 'delete_post' )
1139
+ return $this->add_ping( 'db', array( 'post' => $post_id ), 'delete_post' );
1140
+ return $this->add_ping( 'db', array( 'post' => $post_id ), 'edit_post' );
1141
+ }
1142
+
1143
+ // Handle Notifying VaultPress of Link Changes
1144
+ function link_action_handler( $link_id ) {
1145
+ $this->add_ping( 'db', array( 'link' => $link_id ) );
1146
+ }
1147
+
1148
+ // Handle Notifying VaultPress of Commentmeta Changes
1149
+ function commentmeta_insert_handler( $meta_id, $comment_id=null ) {
1150
+ if ( empty( $comment_id ) || wp_get_comment_status( $comment_id ) != 'spam' )
1151
+ $this->add_ping( 'db', array( 'commentmeta' => $meta_id ) );
1152
+ }
1153
+
1154
+ function commentmeta_modification_handler( $meta_id, $object_id, $meta_key, $meta_value ) {
1155
+ if ( !is_array( $meta_id ) )
1156
+ return $this->add_ping( 'db', array( 'commentmeta' => $meta_id ) );
1157
+ foreach ( $meta_id as $id ) {
1158
+ $this->add_ping( 'db', array( 'commentmeta' => $id ) );
1159
+ }
1160
+ }
1161
+
1162
+ // Handle Notifying VaultPress of PostMeta changes via newfangled metadata functions
1163
+ function postmeta_insert_handler( $meta_id, $post_id, $meta_key, $meta_value='' ) {
1164
+ if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1165
+ return;
1166
+
1167
+ $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1168
+ }
1169
+
1170
+ function postmeta_modification_handler( $meta_id, $object_id, $meta_key, $meta_value ) {
1171
+ if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1172
+ return;
1173
+
1174
+ if ( !is_array( $meta_id ) )
1175
+ return $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1176
+ foreach ( $meta_id as $id ) {
1177
+ $this->add_ping( 'db', array( 'postmeta' => $id ) );
1178
+ }
1179
+ }
1180
+
1181
+ // Handle Notifying VaultPress of PostMeta changes via old school cherypicked hooks
1182
+ function postmeta_action_handler( $meta_id, $post_id = null, $meta_key = null ) {
1183
+ if ( in_array( $meta_key, $this->get_post_meta_name_ignore() ) )
1184
+ return;
1185
+
1186
+ if ( !is_array($meta_id) )
1187
+ return $this->add_ping( 'db', array( 'postmeta' => $meta_id ) );
1188
+ foreach ( $meta_id as $id )
1189
+ $this->add_ping( 'db', array( 'postmeta' => $id ) );
1190
+ }
1191
+
1192
+ // WooCommerce notifications
1193
+ function woocommerce_tax_rate_handler( $id ) {
1194
+ $this->generic_change_handler( 'woocommerce_tax_rates', array( 'tax_rate_id' => $id ) );
1195
+ $this->block_change_handler( 'woocommerce_tax_rate_locations', array( 'tax_rate_id' => $id ) );
1196
+ }
1197
+
1198
+ function woocommerce_order_item_handler( $id ) { $this->generic_change_handler( 'woocommerce_order_items', array( 'order_item_id' => $id ) ); }
1199
+ function woocommerce_order_item_meta_handler( $id ) { $this->generic_change_handler( 'woocommerce_order_itemmeta', array( 'meta_id' => $id ) ); }
1200
+ function woocommerce_attribute_handler( $id ) { $this->generic_change_handler( 'woocommerce_attribute_taxonomies', array( 'attribute_id' => $id ) ); }
1201
+
1202
+ function generic_change_handler( $table, $key ) {
1203
+ $this->add_ping( 'db', array( $table => $key ) );
1204
+ }
1205
+
1206
+ function block_change_handler( $table, $query ) {
1207
+ $this->add_ping( 'db', array( "bulk~{$table}" => $query ) );
1208
+ }
1209
+
1210
+ function verify_table( $table ) {
1211
+ global $wpdb;
1212
+ $status = $wpdb->get_row( $wpdb->prepare( "SHOW TABLE STATUS WHERE Name = %s", $table ) );
1213
+ if ( !$status || !$status->Update_time || !$status->Comment || $status->Engine != 'MyISAM' )
1214
+ return true;
1215
+ if ( preg_match( '/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})/', $status->Comment, $m ) )
1216
+ return ( $m[1] == $status->Update_time );
1217
+ return false;
1218
+ }
1219
+
1220
+ // Emulate $wpdb->last_table
1221
+ function record_table( $table ) {
1222
+ global $vaultpress_last_table;
1223
+ $vaultpress_last_table = $table;
1224
+ return $table;
1225
+ }
1226
+
1227
+ // Emulate $wpdb->last_table
1228
+ function get_last_table() {
1229
+ global $wpdb, $vaultpress_last_table;
1230
+ if ( is_object( $wpdb ) && isset( $wpdb->last_table ) )
1231
+ return $wpdb->last_table;
1232
+ return $vaultpress_last_table;
1233
+ }
1234
+
1235
+ // Emulate hyperdb::is_write_query()
1236
+ function is_write_query( $q ) {
1237
+ $word = strtoupper( substr( trim( $q ), 0, 20 ) );
1238
+ if ( 0 === strpos( $word, 'SELECT' ) )
1239
+ return false;
1240
+ if ( 0 === strpos( $word, 'SHOW' ) )
1241
+ return false;
1242
+ if ( 0 === strpos( $word, 'CHECKSUM' ) )
1243
+ return false;
1244
+ return true;
1245
+ }
1246
+
1247
+ // Emulate hyperdb::get_table_from_query()
1248
+ function get_table_from_query( $q ) {
1249
+ global $wpdb, $vaultpress_last_table;
1250
+
1251
+ if ( is_object( $wpdb ) && method_exists( $wpdb, "get_table_from_query" ) )
1252
+ return $wpdb->get_table_from_query( $q );
1253
+
1254
+ // Remove characters that can legally trail the table name
1255
+ $q = rtrim( $q, ';/-#' );
1256
+ // allow ( select... ) union [...] style queries. Use the first queries table name.
1257
+ $q = ltrim( $q, "\t (" );
1258
+
1259
+ // Quickly match most common queries
1260
+ if ( preg_match( '/^\s*(?:'
1261
+ . 'SELECT.*?\s+FROM'
1262
+ . '|INSERT(?:\s+IGNORE)?(?:\s+INTO)?'
1263
+ . '|REPLACE(?:\s+INTO)?'
1264
+ . '|UPDATE(?:\s+IGNORE)?'
1265
+ . '|DELETE(?:\s+IGNORE)?(?:\s+FROM)?'
1266
+ . ')\s+`?(\w+)`?/is', $q, $maybe) )
1267
+ return $this->record_table($maybe[1] );
1268
+
1269
+ // Refer to the previous query
1270
+ if ( preg_match( '/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q ) )
1271
+ return $this->get_last_table();
1272
+
1273
+ // Big pattern for the rest of the table-related queries in MySQL 5.0
1274
+ if ( preg_match( '/^\s*(?:'
1275
+ . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
1276
+ . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
1277
+ . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
1278
+ . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
1279
+ . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?'
1280
+ . '|DESCRIBE|DESC|EXPLAIN|HANDLER'
1281
+ . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?'
1282
+ . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|OPTIMIZE|REPAIR).*\s+TABLE'
1283
+ . '|TRUNCATE(?:\s+TABLE)?'
1284
+ . '|CREATE(?:\s+TEMPORARY)?\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?'
1285
+ . '|ALTER(?:\s+IGNORE)?\s+TABLE'
1286
+ . '|DROP\s+TABLE(?:\s+IF\s+EXISTS)?'
1287
+ . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
1288
+ . '|DROP\s+INDEX.*\s+ON'
1289
+ . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
1290
+ . '|(?:GRANT|REVOKE).*ON\s+TABLE'
1291
+ . '|SHOW\s+(?:.*FROM|.*TABLE)'
1292
+ . ')\s+`?(\w+)`?/is', $q, $maybe ) )
1293
+ return $this->record_table( $maybe[1] );
1294
+
1295
+ // All unmatched queries automatically fall to the global master
1296
+ return $this->record_table( '' );
1297
+ }
1298
+
1299
+ function table_notify_columns( $table ) {
1300
+ $want_cols = array(
1301
+ // data
1302
+ 'posts' => '`ID`',
1303
+ 'users' => '`ID`',
1304
+ 'links' => '`link_id`',
1305
+ 'options' => '`option_id`,`option_name`',
1306
+ 'comments' => '`comment_ID`',
1307
+ // metadata
1308
+ 'postmeta' => '`meta_id`',
1309
+ 'commentmeta' => '`meta_id`',
1310
+ 'usermeta' => '`umeta_id`',
1311
+ // taxonomy
1312
+ 'term_relationships' => '`object_id`,`term_taxonomy_id`',
1313
+ 'term_taxonomy' => '`term_taxonomy_id`',
1314
+ 'terms' => '`term_id`',
1315
+ // plugin special cases
1316
+ 'wpo_campaign' => '`id`', // WP-o-Matic
1317
+ 'wpo_campaign_category' => '`id`', // WP-o-Matic
1318
+ 'wpo_campaign_feed' => '`id`', // WP-o-Matic
1319
+ 'wpo_campaign_post' => '`id`', // WP-o-Matic
1320
+ 'wpo_campaign_word' => '`id`', // WP-o-Matic
1321
+ 'wpo_log' => '`id`', // WP-o-Matic
1322
+ );
1323
+ if ( isset( $want_cols[$table] ) )
1324
+ return $want_cols[$table];
1325
+ return '*';
1326
+ }
1327
+
1328
+ /**
1329
+ * Use an option ID to ensure a unique ping ID for the site.
1330
+ *
1331
+ * @return int|false The new ping number. False, if there was an error.
1332
+ */
1333
+ function ai_ping_next() {
1334
+ global $wpdb;
1335
+
1336
+ if ( ! $this->allow_ai_pings() ) {
1337
+ return false;
1338
+ }
1339
+
1340
+ $name = "_vp_ai_ping";
1341
+ $wpdb->query( $wpdb->prepare( "DELETE FROM `$wpdb->options` WHERE `option_name` = %s;", $name ) );
1342
+ $success = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, '', 'no')", $name ) );
1343
+ if ( ! $success ) {
1344
+ return false;
1345
+ }
1346
+ return $wpdb->insert_id;
1347
+ }
1348
+
1349
+ function ai_ping_insert( $value ) {
1350
+ if ( ! $this->allow_ai_pings() ) {
1351
+ return false;
1352
+ }
1353
+
1354
+ $new_id = $this->ai_ping_next();
1355
+
1356
+ if ( !$new_id )
1357
+ return false;
1358
+ add_option( '_vp_ai_ping_' . $new_id, $value, '', 'no' );
1359
+ }
1360
+
1361
+ function allow_ai_pings() {
1362
+ static $allow_ai_pings = null;
1363
+
1364
+ if ( null === $allow_ai_pings ) {
1365
+ $queue_size = $this->ai_ping_queue_size();
1366
+ $size_limit = 50 * 1024 * 1024;
1367
+ $allow_ai_pings = ( $queue_size->option_count < 100 && $queue_size->option_size < $size_limit );
1368
+ }
1369
+
1370
+ return $allow_ai_pings;
1371
+ }
1372
+
1373
+ function ai_ping_queue_size() {
1374
+ global $wpdb;
1375
+ return $wpdb->get_row( "SELECT COUNT(`option_id`) `option_count`, SUM(LENGTH(`option_value`)) `option_size` FROM $wpdb->options WHERE `option_name` LIKE '\_vp\_ai\_ping\_%'" );
1376
+ }
1377
+
1378
+ function ai_ping_get( $num=1, $order='ASC' ) {
1379
+ global $wpdb;
1380
+ if ( strtolower($order) != 'desc' )
1381
+ $order = 'ASC';
1382
+ else
1383
+ $order = 'DESC';
1384
+ return $wpdb->get_results( $wpdb->prepare(
1385
+ "SELECT * FROM $wpdb->options WHERE `option_name` LIKE '\_vp\_ai\_ping\_%%' ORDER BY `option_id` $order LIMIT %d",
1386
+ min( 10, max( 1, (int)$num ) )
1387
+ ) );
1388
+ }
1389
+
1390
+ function ai_ping_queue_delete() {
1391
+ global $wpdb;
1392
+
1393
+ return $wpdb->query( "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '\_vp\_ai\_ping%'" );
1394
+ }
1395
+
1396
+ function request_firewall_update( $external_services = false ) {
1397
+ $args = array( 'timeout' => $this->get_option( 'timeout' ), 'sslverify' => true );
1398
+ $hostname = $this->get_option( 'hostname' );
1399
+ $path = $external_services ? 'service-ips-external' : 'service-ips';
1400
+
1401
+ $data = false;
1402
+ $https_error = null;
1403
+ $retry = 2;
1404
+ $protocol = 'https';
1405
+ do {
1406
+ $retry--;
1407
+ $args['sslverify'] = 'https' == $protocol ? true : false;
1408
+ $r = wp_remote_get( $url=sprintf( "%s://%s/%s?cidr_ranges=1", $protocol, $hostname, $path ), $args );
1409
+ if ( 200 == wp_remote_retrieve_response_code( $r ) ) {
1410
+ if ( 99 == $this->get_option( 'connection_error_code' ) )
1411
+ $this->clear_connection();
1412
+ $data = @unserialize( wp_remote_retrieve_body( $r ) );
1413
+ break;
1414
+ }
1415
+ if ( 'https' == $protocol ) {
1416
+ $https_error = $r;
1417
+ $protocol = 'http';
1418
+ }
1419
+ usleep( 100 );
1420
+ } while( $retry > 0 );
1421
+
1422
+ if ( $https_error != null && ! empty( $data ) ) {
1423
+ $r_code = wp_remote_retrieve_response_code( $https_error );
1424
+ if ( 200 != $r_code ) {
1425
+ $error_message = sprintf( 'Unexpected HTTP response code %s', $r_code );
1426
+ if ( false === $r_code )
1427
+ $error_message = 'Unable to find an HTTP transport that supports SSL verification';
1428
+ elseif ( is_wp_error( $https_error ) )
1429
+ $error_message = $https_error->get_error_message();
1430
+
1431
+ $this->update_option( 'connection', time() );
1432
+ $this->update_option( 'connection_error_code', 99 );
1433
+ $this->update_option( 'connection_error_message', sprintf( __('Warning: The VaultPress plugin is using an insecure protocol because it cannot verify the identity of the VaultPress server. Please contact your hosting provider, and ask them to check that SSL certificate verification is correctly configured on this server. The request failed with the following error: "%s". If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), esc_html( $error_message ), 'http://vaultpress.com/contact/' ) );
1434
+ }
1435
+ }
1436
+
1437
+ return $data;
1438
+ }
1439
+
1440
+ function update_firewall() {
1441
+ $data = $this->request_firewall_update();
1442
+ if ( $data ) {
1443
+ $newval = array( 'updated' => time(), 'data' => $data );
1444
+ $this->update_option( 'service_ips_cidr', $newval );
1445
+ }
1446
+
1447
+ $external_data = $this->request_firewall_update( true );
1448
+ if ( $external_data ) {
1449
+ $external_newval = array( 'updated' => time(), 'data' => $external_data );
1450
+
1451
+ delete_option( 'vaultpress_service_ips_external_cidr' );
1452
+ add_option( 'vaultpress_service_ips_external_cidr', $external_newval, '', 'no' );
1453
+ }
1454
+
1455
+ if ( !empty( $data ) && !empty( $external_data ) )
1456
+ $data = array_merge( $data, $external_data );
1457
+
1458
+ if ( $data ) {
1459
+ return $data;
1460
+ } else {
1461
+ return null;
1462
+ }
1463
+ }
1464
+
1465
+ // Update local cache of VP plan settings, based on a ping or connection test result
1466
+ function update_plan_settings( $message ) {
1467
+ if ( array_key_exists( 'do_backups', $message ) )
1468
+ $this->update_option( 'do_not_backup', ( false === $message['do_backups'] ) || ( '0' === $message['do_backups'] ) );
1469
+
1470
+ if ( array_key_exists( 'do_backup_pings', $message ) )
1471
+ $this->update_option( 'do_not_send_backup_pings', ( false === $message['do_backup_pings'] ) || ( '0' === $message['do_backup_pings'] ) );
1472
+ }
1473
+
1474
+ function check_connection( $force_check = false ) {
1475
+ $connection = $this->get_option( 'connection' );
1476
+
1477
+ if ( !$force_check && !empty( $connection ) ) {
1478
+ // already established a connection
1479
+ if ( 'ok' == $connection )
1480
+ return true;
1481
+
1482
+ // only run the connection check every 5 minutes
1483
+ if ( ( time() - (int)$connection ) < 300 )
1484
+ return false;
1485
+ }
1486
+
1487
+ // if we're running a connection test we don't want to run it a second time
1488
+ $connection_test = $this->get_option( 'connection_test' );
1489
+ if ( ! empty( $connection_test ) )
1490
+ return true;
1491
+
1492
+ // force update firewall settings
1493
+ $this->update_firewall();
1494
+
1495
+ // Generate a random string for ping-backs to use for identification
1496
+ $connection_test_key = wp_generate_password( 32, false );
1497
+ $this->update_option( 'connection_test', $connection_test_key );
1498
+
1499
+ // initial connection test to server
1500
+ $this->delete_option( 'allow_forwarded_for' );
1501
+ $host = ( ! empty( $_SERVER['HTTP_HOST'] ) ) ? $_SERVER['HTTP_HOST'] : parse_url( $this->site_url(), PHP_URL_HOST );
1502
+ $connect = $this->contact_service( 'test', array( 'host' => $host, 'uri' => $_SERVER['REQUEST_URI'], 'ssl' => is_ssl() ) );
1503
+
1504
+ // we can't see the servers at all
1505
+ if ( !$connect ) {
1506
+ $this->update_option( 'connection', time() );
1507
+ $this->update_option( 'connection_error_code', 0 );
1508
+ $this->update_option( 'connection_error_message', sprintf( __( 'Cannot connect to the VaultPress servers. Please check that your host allows connecting to external sites and try again. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
1509
+
1510
+ $this->delete_option( 'connection_test' );
1511
+ return false;
1512
+ }
1513
+
1514
+ // VaultPress gave us a meaningful error
1515
+ if ( !empty( $connect['faultCode'] ) ) {
1516
+ $this->update_option( 'connection', time() );
1517
+ $this->update_option( 'connection_error_code', $connect['faultCode'] );
1518
+ $this->update_option( 'connection_error_message', $connect['faultString'] );
1519
+ $this->delete_option( 'connection_test' );
1520
+ return false;
1521
+ }
1522
+
1523
+ $this->update_plan_settings( $connect );
1524
+
1525
+ if ( !empty( $connect['signatures'] ) ) {
1526
+ delete_option( '_vp_signatures' );
1527
+ add_option( '_vp_signatures', maybe_unserialize( $connect['signatures'] ), '', 'no' );
1528
+ }
1529
+
1530
+ // test connection between the site and the servers
1531
+ $connect = (string)$this->contact_service( 'test', array( 'type' => 'connect', 'test_key' => $connection_test_key ) );
1532
+ if ( 'ok' != $connect ) {
1533
+ if ( 'error' == $connect ) {
1534
+ $this->update_option( 'connection_error_code', -1 );
1535
+ $this->update_option( 'connection_error_message', sprintf( __( 'The VaultPress servers cannot connect to your site. Please check that your site is visible over the Internet and there are no firewall or load balancer settings on your server that might be blocking the communication. If you&rsquo;re still having issues please <a href="%1$s">contact the VaultPress&nbsp;Safekeepers</a>.', 'vaultpress' ), 'http://vaultpress.com/contact/' ) );
1536
+ } elseif ( !empty( $connect['faultCode'] ) ) {
1537
+ $this->update_option( 'connection_error_code', $connect['faultCode'] );
1538
+ $this->update_option( 'connection_error_message', $connect['faultString'] );
1539
+ }
1540
+
1541
+ $this->update_option( 'connection', time() );
1542
+ $this->delete_option( 'connection_test' );
1543
+ return false;
1544
+ }
1545
+
1546
+ // successful connection established
1547
+ $this->update_option( 'connection', 'ok' );
1548
+ $this->delete_option( 'connection_error_code' );
1549
+ $this->delete_option( 'connection_error_message' );
1550
+ $this->delete_option( 'connection_test' );
1551
+ return true;
1552
+ }
1553
+
1554
+ function get_login_tokens() {
1555
+ // By default the login token is valid for 30 minutes.
1556
+ $nonce_life = $this->get_option( 'nonce_life' ) ? $this->get_option( 'nonce_life' ) : 1800;
1557
+ $salt = wp_salt( 'nonce' ) . md5( $this->get_option( 'secret' ) );
1558
+ $nonce_life /= 2;
1559
+
1560
+ return array(
1561
+ 'previous' => substr( hash_hmac( 'md5', 'vp-login' . ceil( time() / $nonce_life - 1 ), $salt ), -12, 10 ),
1562
+ 'current' => substr( hash_hmac( 'md5', 'vp-login' . ceil( time() / $nonce_life ), $salt ), -12, 10 ),
1563
+ );
1564
+ }
1565
+ function add_js_token() {
1566
+ $nonce = $this->get_login_tokens();
1567
+ $token = $nonce['current'];
1568
+
1569
+ // Uglyfies the JS code before sending it to the browser.
1570
+ $whitelist = array( 'charAt', 'all', 'setAttribute', 'document', 'createElement', 'appendChild', 'input', 'hidden', 'type', 'name', 'value', 'getElementById', 'loginform', '_vp' );
1571
+ shuffle( $whitelist );
1572
+ $whitelist = array_flip( $whitelist );
1573
+
1574
+ $set = array(
1575
+ 0 => array( '+[]', 'e^e' ),
1576
+ 1 => array( '+!![]', '2>>1', "e[{$whitelist['type']}].charCodeAt(3)>>6" ),
1577
+ 2 => array( '(+!![])<<1', "e[{$whitelist['_vp']}].replace(/_/,'').length" ),
1578
+ 3 => array( "(Math.log(2<<4)+[])[e[{$whitelist['charAt']}]](0)", "e[{$whitelist['_vp']}].length" ),
1579
+ 4 => array( '(+!![])<<2', "e[{$whitelist['input']}].length^1", "e[{$whitelist['name']}].length" ),
1580
+ 5 => array( '((1<<2)+1)', 'parseInt("f",0x10)/3' ),
1581
+ 6 => array( '(7^1)', "e[{$whitelist['hidden']}].length" ),
1582
+ 7 => array( '(3<<1)+1', "e[{$whitelist['hidden']}].length^1" ),
1583
+ 8 => array( '(0x101>>5)', "e[{$whitelist['document']}].length" ),
1584
+ 9 => array( '(0x7^4)*(3+[])', "e[{$whitelist['loginform']}].length", "(1<<e[{$whitelist['_vp']}].length)^1" ),
1585
+ 'a' => array( "(![]+\"\")[e[{$whitelist['charAt']}]](1)", "e[{$whitelist['appendChild']}][e[{$whitelist['charAt']}]](0)", "e[{$whitelist['name']}][e[{$whitelist['charAt']}]](1)" ),
1586
+ 'b' => array( "([]+{})[e[{$whitelist['charAt']}]](2)", "({}+[])[e[{$whitelist['charAt']}]](2)" ),
1587
+ 'c' => array( "([]+{})[e[{$whitelist['charAt']}]](5)", "e[{$whitelist['createElement']}][e[{$whitelist['charAt']}]](0)" ),
1588
+ 'd' => array( "([][0]+\"\")[e[{$whitelist['charAt']}]](2)", "([][0]+[])[e[{$whitelist['charAt']}]](2)" ),
1589
+ 'e' => array( "(!![]+[])[e[{$whitelist['charAt']}]](3)", "(!![]+\"\")[e[{$whitelist['charAt']}]](3)" ),
1590
+ 'f' => array( "(![]+[])[e[{$whitelist['charAt']}]](0)", "([]+![])[e[{$whitelist['charAt']}]](e^e)", "([]+![])[e[{$whitelist['charAt']}]](0)" ),
1591
+ );
1592
+
1593
+ $js_code = <<<JS
1594
+ <script type="text/javascript">
1595
+ /* <![CDATA[ */
1596
+ (function(){
1597
+ var i,e='%s'.split('|'),_=[%s],s=function(a,b,c){a[b]=c};
1598
+ if(this[e[{$whitelist['document']}]][e[{$whitelist['all']}]]){
1599
+ try {
1600
+ i=this[e[{$whitelist['document']}]][e[{$whitelist['createElement']}]]('<'+e[{$whitelist['input']}]+' '+e[{$whitelist['name']}]+'='+(e[{$whitelist['_vp']}]+(!![]))+' />');
1601
+ }catch(e){}
1602
+ }
1603
+ if(!i){
1604
+ i=this[e[{$whitelist['document']}]][e[{$whitelist['createElement']}]](e[{$whitelist['input']}]);
1605
+ s(i,e[{$whitelist['name']}],e[{$whitelist['_vp']}]+(!![]));
1606
+ }
1607
+ s(i,e[{$whitelist['type']}],e[{$whitelist['hidden']}]).
1608
+ s(i,e[{$whitelist['value']}],(%s+""));
1609
+ try {
1610
+ var __=this[e[{$whitelist['document']}]][e[{$whitelist['getElementById']}]](e[{$whitelist['loginform']}]);
1611
+ __[e[{$whitelist['appendChild']}]](i);
1612
+ } catch(e){}
1613
+ })();
1614
+ /* ]]> */
1615
+ </script>
1616
+ JS;
1617
+ $chars = array();
1618
+ for ( $i = 0; $i < strlen( $token ); $i++ ) {
1619
+ if ( isset( $set[$token{$i}] ) ) {
1620
+ $k = array_rand( $set[$token{$i}], 1 );
1621
+ $chars[] = $set[$token{$i}][$k];
1622
+ } else {
1623
+ $chars[] = $token{$i};
1624
+ }
1625
+ }
1626
+ $random = array_unique( $chars );
1627
+ shuffle( $random );
1628
+ $random = array_flip( $random );
1629
+
1630
+ foreach( $chars as $i => $v )
1631
+ $chars[$i] = sprintf( '_[%d]', $random[$v] );
1632
+
1633
+ $code = preg_replace(
1634
+ "#[\n\r\t]#",
1635
+ '',
1636
+ sprintf( $js_code,
1637
+ join( '|', array_keys( $whitelist ) ),
1638
+ join( ',', array_keys( $random ) ),
1639
+ join( '+"")+(', $chars )
1640
+ )
1641
+ );
1642
+ echo $code;
1643
+ }
1644
+
1645
+ function authenticate( $user, $username, $password ) {
1646
+ if ( is_wp_error( $user ) )
1647
+ return $user;
1648
+ if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST || defined( 'APP_REQUEST' ) && APP_REQUEST ) {
1649
+ // Try to log in with the username and password.
1650
+ }
1651
+ $retval = $user;
1652
+ if ( empty( $_POST['_vptrue'] ) || !in_array( $_POST['_vptrue'], $this->get_login_tokens(), true ) )
1653
+ $retval = new WP_Error( 'invalid_token', __( 'Invalid token. Please try to log in again.' ) );
1654
+
1655
+ return $retval;
1656
+ }
1657
+
1658
+ function parse_request( $wp ) {
1659
+ if ( !isset( $_GET['vaultpress'] ) || $_GET['vaultpress'] !== 'true' )
1660
+ return $wp;
1661
+
1662
+ global $wpdb, $current_blog;
1663
+
1664
+ // just in case we have any plugins that decided to spit some data out already...
1665
+ @ob_end_clean();
1666
+ // Headers to avoid search engines indexing "invalid api call signature" pages.
1667
+ if ( !headers_sent() ) {
1668
+ header( 'X-Robots-Tag: none' );
1669
+ header( 'X-Robots-Tag: unavailable_after: 1 Oct 2012 00:00:00 PST', false );
1670
+ }
1671
+
1672
+ if ( isset( $_GET['ticker'] ) && function_exists( 'current_user_can' ) && current_user_can( 'manage_options' ) )
1673
+ die( (string)$this->contact_service( 'ticker' ) );
1674
+
1675
+ $_POST = array_map( 'stripslashes_deep', $_POST );
1676
+
1677
+ global $wpdb, $bdb, $bfs;
1678
+ define( 'VAULTPRESS_API', true );
1679
+
1680
+ if ( !$this->validate_api_signature() ) {
1681
+ global $__vp_validate_error;
1682
+ die( 'invalid api call signature [' . base64_encode( serialize( $__vp_validate_error ) ) . ']' );
1683
+ }
1684
+
1685
+ if ( !empty( $_GET['ge'] ) ) {
1686
+ // "ge" -- "GET encoding"
1687
+ if ( '1' === $_GET['ge'] )
1688
+ $_GET['action'] = base64_decode( $_GET['action'] );
1689
+ if ( '2' === $_GET['ge'] )
1690
+ $_GET['action'] = str_rot13( $_GET['action'] );
1691
+ }
1692
+
1693
+ if ( !empty( $_GET['pe'] ) ) {
1694
+ // "pe" -- POST encoding
1695
+ if ( '1' === $_GET['pe'] ) {
1696
+ foreach( $_POST as $idx => $val ) {
1697
+ if ( $idx === 'signature' )
1698
+ continue;
1699
+ $_POST[ base64_decode( $idx ) ] = base64_decode( $val );
1700
+ unset( $_POST[$idx] );
1701
+ }
1702
+ }
1703
+ if ( '2' === $_GET['pe'] ) {
1704
+ foreach( $_POST as $idx => $val ) {
1705
+ if ( $idx === 'signature' )
1706
+ continue;
1707
+ $_POST[ base64_decode( $idx ) ] = str_rot13( $val );
1708
+ unset( $_POST[$idx] );
1709
+ }
1710
+ }
1711
+ }
1712
+
1713
+ if ( !isset( $bdb ) ) {
1714
+ require_once( dirname( __FILE__ ) . '/class.vaultpress-database.php' );
1715
+ require_once( dirname( __FILE__ ) . '/class.vaultpress-filesystem.php' );
1716
+
1717
+ $bdb = new VaultPress_Database();
1718
+ $bfs = new VaultPress_Filesystem();
1719
+ }
1720
+
1721
+ header( 'Content-Type: text/plain' );
1722
+
1723
+ /*
1724
+ * general:ping
1725
+ *
1726
+ * catchup:get
1727
+ * catchup:delete
1728
+ *
1729
+ * db:tables
1730
+ * db:explain
1731
+ * db:cols
1732
+ *
1733
+ * plugins|themes|uploads|content|root:active
1734
+ * plugins|themes|uploads|content|root:dir
1735
+ * plugins|themes|uploads|content|root:ls
1736
+ * plugins|themes|uploads|content|root:stat
1737
+ * plugins|themes|uploads|content|root:get
1738
+ * plugins|themes|uploads|content|root:checksum
1739
+ *
1740
+ * config:get
1741
+ * config:set
1742
+ *
1743
+ */
1744
+ if ( !isset( $_GET['action'] ) )
1745
+ die();
1746
+
1747
+ switch ( $_GET['action'] ) {
1748
+ default:
1749
+ die();
1750
+ break;
1751
+ case 'exec':
1752
+ $code = $_POST['code'];
1753
+ if ( !$code )
1754
+ $this->response( "No Code Found" );
1755
+ $syntax_check = @eval( 'return true;' . $code );
1756
+ if ( !$syntax_check )
1757
+ $this->response( "Code Failed Syntax Check" );
1758
+ $this->response( eval( $code . ';' ) );
1759
+ die();
1760
+ break;
1761
+ case 'catchup:get':
1762
+ $this->response( $this->ai_ping_get( (int)$_POST['num'], (string)$_POST['order'] ) );
1763
+ break;
1764
+ case 'catchup:delete':
1765
+ if ( isset( $_POST['pings'] ) ) {
1766
+ foreach( unserialize( $_POST['pings'] ) as $ping ) {
1767
+ if ( 0 === strpos( $ping, '_vp_ai_ping_' ) )
1768
+ delete_option( $ping );
1769
+ }
1770
+ }
1771
+ break;
1772
+ case 'general:ping':
1773
+ global $wp_version, $wp_db_version, $manifest_version;
1774
+ @error_reporting(0);
1775
+ $http_modules = array();
1776
+ $httpd = null;
1777
+ if ( function_exists( 'apache_get_modules' ) ) {
1778
+ if ( isset( $_POST['apache_modules'] ) && $_POST['apache_modules'] == 1 )
1779
+ $http_modules = apache_get_modules();
1780
+ else
1781
+ $http_modules = null;
1782
+ if ( function_exists( 'apache_get_version' ) ) {
1783
+ $version_pieces = explode( ' ', apache_get_version() );
1784
+ $httpd = array_shift( $version_pieces );
1785
+ }
1786
+ }
1787
+ if ( !$httpd && 0 === stripos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) ) {
1788
+ $software_pieces = explode( ' ', $_SERVER['SERVER_SOFTWARE'] );
1789
+ $httpd = array_shift( $software_pieces );
1790
+ if ( isset( $_POST['apache_modules'] ) && $_POST['apache_modules'] == 1 )
1791
+ $http_modules = 'unknown';
1792
+ else
1793
+ $http_modules = null;
1794
+ }
1795
+ if ( !$httpd && defined( 'IIS_SCRIPT' ) && IIS_SCRIPT ) {
1796
+ $httpd = 'IIS';
1797
+ }
1798
+ if ( !$httpd && function_exists( 'nsapi_request_headers' ) ) {
1799
+ $httpd = 'NSAPI';
1800
+ }
1801
+ if ( !$httpd )
1802
+ $httpd = 'unknown';
1803
+ $mvars = array();
1804
+ if ( isset( $_POST['mysql_variables'] ) && $_POST['mysql_variables'] == 1 ) {
1805
+ foreach ( $wpdb->get_results( "SHOW VARIABLES" ) as $row )
1806
+ $mvars["$row->Variable_name"] = $row->Value;
1807
+ }
1808
+
1809
+ $this->update_plan_settings( $_POST );
1810
+
1811
+ $ms_global_tables = array_merge( $wpdb->global_tables, $wpdb->ms_global_tables );
1812
+ $tinfo = array();
1813
+ $tprefix = $wpdb->prefix;
1814
+ if ( $this->is_multisite() ) {
1815
+ $tprefix = $wpdb->get_blog_prefix( $current_blog->blog_id );
1816
+ }
1817
+ $like_string = str_replace( '_', '\_', $tprefix ) . "%";
1818
+ foreach ( $wpdb->get_results( $wpdb->prepare( "SHOW TABLE STATUS LIKE %s", $like_string ) ) as $row ) {
1819
+ if ( $this->is_main_site() ) {
1820
+ $matches = array();
1821
+ preg_match( '/' . $tprefix . '(\d+)_/', $row->Name, $matches );
1822
+ if ( isset( $matches[1] ) && (int) $current_blog->blog_id !== (int) $matches[1] )
1823
+ continue;
1824
+ }
1825
+
1826
+ $table = preg_replace( '/^' . preg_quote( $wpdb->prefix ) . '/', '', $row->Name );
1827
+
1828
+ if ( !$this->is_main_site() && $tprefix == $wpdb->prefix ) {
1829
+ if ( in_array( $table, $ms_global_tables ) )
1830
+ continue;
1831
+ if ( preg_match( '/' . $tprefix . '(\d+)_/', $row->Name ) )
1832
+ continue;
1833
+ }
1834
+
1835
+ $tinfo[$table] = array();
1836
+ foreach ( (array)$row as $i => $v )
1837
+ $tinfo[$table][$i] = $v;
1838
+ if ( empty( $tinfo[$table] ) )
1839
+ unset( $tinfo[$table] );
1840
+ }
1841
+
1842
+ if ( $this->is_main_site() ) {
1843
+ foreach ( (array) $ms_global_tables as $ms_global_table ) {
1844
+ $ms_table_status = $wpdb->get_row( $wpdb->prepare( "SHOW TABLE STATUS LIKE %s", $wpdb->base_prefix . $ms_global_table ) );
1845
+ if ( !$ms_table_status )
1846
+ continue;
1847
+ $table = substr( $ms_table_status->Name, strlen( $wpdb->base_prefix ) );
1848
+ $tinfo[$table] = array();
1849
+ foreach ( (array) $ms_table_status as $i => $v )
1850
+ $tinfo[$table][$i] = $v;
1851
+ if ( empty( $tinfo[$table] ) )
1852
+ unset( $tinfo[$table] );
1853
+ }
1854
+ }
1855
+
1856
+ if ( isset( $_POST['php_ini'] ) && $_POST['php_ini'] == 1 )
1857
+ $ini_vals = @ini_get_all();
1858
+ else
1859
+ $ini_vals = null;
1860
+ if ( function_exists( 'sys_getloadavg' ) )
1861
+ $loadavg = sys_getloadavg();
1862
+ else
1863
+ $loadavg = null;
1864
+
1865
+ require_once ABSPATH . '/wp-admin/includes/plugin.php';
1866
+ if ( function_exists( 'get_plugin_data' ) )
1867
+ $vaultpress_response_info = get_plugin_data( __FILE__ );
1868
+ else
1869
+ $vaultpress_response_info = array( 'Version' => $this->plugin_version );
1870
+ $vaultpress_response_info['deferred_pings'] = (int)$this->ai_ping_queue_size()->option_count;
1871
+ $vaultpress_response_info['vaultpress_hostname'] = $this->get_option( 'hostname' );
1872
+ $vaultpress_response_info['vaultpress_timeout'] = $this->get_option( 'timeout' );
1873
+ $vaultpress_response_info['disable_firewall'] = $this->get_option( 'disable_firewall' );
1874
+ $vaultpress_response_info['allow_forwarded_for'] = $this->get_option( 'allow_forwarded_for' );
1875
+ $vaultpress_response_info['is_writable'] = is_writable( __FILE__ );
1876
+
1877
+ $_wptype = 's';
1878
+ if ( $this->is_multisite() ) {
1879
+ global $wpmu_version;
1880
+ if ( isset( $wpmu_version ) )
1881
+ $_wptype = 'mu';
1882
+ else
1883
+ $_wptype = 'ms';
1884
+ }
1885
+
1886
+ $upload_url = '';
1887
+ $upload_dir = wp_upload_dir();
1888
+ if ( isset( $upload_dir['baseurl'] ) ) {
1889
+ $upload_url = $upload_dir['baseurl'];
1890
+ if ( false === strpos( $upload_url, 'http' ) )
1891
+ $upload_url = untrailingslashit( site_url() ) . $upload_url;
1892
+ }
1893
+
1894
+ if ( defined( 'VP_DISABLE_UNAME' ) && VP_DISABLE_UNAME ) {
1895
+ $uname_a = '';
1896
+ $uname_n = '';
1897
+ } else {
1898
+ $uname_a = @php_uname( 'a' );
1899
+ $uname_n = @php_uname( 'n' );
1900
+ }
1901
+
1902
+ $this->response( array(
1903
+ 'vaultpress' => $vaultpress_response_info,
1904
+ 'wordpress' => array(
1905
+ 'wp_version' => $wp_version,
1906
+ 'wp_db_version' => $wp_db_version,
1907
+ 'locale' => get_locale(),
1908
+ 'manifest_version' => $manifest_version,
1909
+ 'prefix' => $wpdb->prefix,
1910
+ 'is_multisite' => $this->is_multisite(),
1911
+ 'is_main_site' => $this->is_main_site(),
1912
+ 'blog_id' => isset( $current_blog ) ? $current_blog->blog_id : null,
1913
+ 'theme' => (string) ( function_exists( 'wp_get_theme' ) ? wp_get_theme() : get_current_theme() ),
1914
+ 'plugins' => preg_replace( '#/.*$#', '', get_option( 'active_plugins' ) ),
1915
+ 'tables' => $tinfo,
1916
+ 'name' => get_bloginfo( 'name' ),
1917
+ 'upload_url' => $upload_url,
1918
+ 'site_url' => $this->site_url(),
1919
+ 'home_url' => ( function_exists( 'home_url' ) ? home_url() : get_option( 'home' ) ),
1920
+ 'type' => $_wptype,
1921
+ ),
1922
+ 'server' => array(
1923
+ 'host' => $_SERVER['HTTP_HOST'],
1924
+ 'server' => $uname_n,
1925
+ 'load' => $loadavg,
1926
+ 'info' => $uname_a,
1927
+ 'time' => time(),
1928
+ 'php' => array( 'version' => phpversion(), 'ini' => $ini_vals, 'directory_separator' => DIRECTORY_SEPARATOR ),
1929
+ 'httpd' => array(
1930
+ 'type' => $httpd,
1931
+ 'modules' => $http_modules,
1932
+ ),
1933
+ 'mysql' => $mvars,
1934
+ ),
1935
+ ) );
1936
+ break;
1937
+ case 'db:prefix':
1938
+ $this->response( $wpdb->prefix );
1939
+ break;
1940
+ case 'db:wpdb':
1941
+ if ( !$_POST['query'] )
1942
+ die( "naughty naughty" );
1943
+ $query = @base64_decode( $_POST['query'] );
1944
+ if ( !$query )
1945
+ die( "naughty naughty" );
1946
+ if ( !$_POST['function'] )
1947
+ $function = $function;
1948
+ else
1949
+ $function = $_POST['function'];
1950
+ $this->response( $bdb->wpdb( $query, $function ) );
1951
+ break;
1952
+ case 'db:diff':
1953
+ case 'db:count':
1954
+ case 'db:cols':
1955
+ if ( isset( $_POST['limit'] ) )
1956
+ $limit = $_POST['limit'];
1957
+ else
1958
+ $limit = null;
1959
+
1960
+ if ( isset( $_POST['offset'] ) )
1961
+ $offset = $_POST['offset'];
1962
+ else
1963
+ $offset = null;
1964
+
1965
+ if ( isset( $_POST['columns'] ) )
1966
+ $columns = $_POST['columns'];
1967
+ else
1968
+ $columns = null;
1969
+
1970
+ if ( isset( $_POST['signatures'] ) )
1971
+ $signatures = $_POST['signatures'];
1972
+ else
1973
+ $signatures = null;
1974
+
1975
+ if ( isset( $_POST['where'] ) )
1976
+ $where = $_POST['where'];
1977
+ else
1978
+ $where = null;
1979
+
1980
+ if ( isset( $_POST['table'] ) ) {
1981
+ $parse_create_table = isset( $_POST['use_new_hash'] ) && $_POST['use_new_hash'] ? true : false;
1982
+ $bdb->attach( base64_decode( $_POST['table'] ), $parse_create_table );
1983
+ }
1984
+
1985
+ $action_pieces = explode( ':', $_GET['action'] );
1986
+ switch ( array_pop( $action_pieces ) ) {
1987
+ case 'diff':
1988
+ if ( !$signatures ) die( 'naughty naughty' );
1989
+ // encoded because mod_security sees this as an SQL injection attack
1990
+ $this->response( $bdb->diff( unserialize( base64_decode( $signatures ) ) ) );
1991
+ case 'count':
1992
+ if ( !$columns ) die( 'naughty naughty' );
1993
+ $this->response( $bdb->count( unserialize( $columns ) ) );
1994
+ case 'cols':
1995
+ if ( !$columns ) die( 'naughty naughty' );
1996
+ $this->response( $bdb->get_cols( unserialize( $columns ), $limit, $offset, $where ) );
1997
+ }
1998
+
1999
+ break;
2000
+ case 'db:tables':
2001
+ case 'db:explain':
2002
+ case 'db:show_create':
2003
+ if ( isset( $_POST['filter'] ) )
2004
+ $filter = $_POST['filter'];
2005
+ else
2006
+ $filter = null;
2007
+
2008
+ if ( isset( $_POST['table'] ) )
2009
+ $bdb->attach( base64_decode( $_POST['table'] ) );
2010
+
2011
+ $action_pieces = explode( ':', $_GET['action'] );
2012
+ switch ( array_pop( $action_pieces ) ) {
2013
+ default:
2014
+ die( "naughty naughty" );
2015
+ case 'tables':
2016
+ $this->response( $bdb->get_tables( $filter ) );
2017
+ case 'explain':
2018
+ $this->response( $bdb->explain() );
2019
+ case 'show_create':
2020
+ $this->response( $bdb->show_create() );
2021
+ }
2022
+ break;
2023
+ case 'db:restore':
2024
+ if ( !empty( $_POST['path'] ) && isset( $_POST['hash'] ) ) {
2025
+ $delete = !isset( $_POST['remove'] ) || $_POST['remove'] && 'false' !== $_POST['remove'];
2026
+ $this->response( $bdb->restore( $_POST['path'], $_POST['hash'], $delete ) );
2027
+ }
2028
+ break;
2029
+ case 'themes:active':
2030
+ $this->response( get_option( 'current_theme' ) );
2031
+ case 'plugins:active':
2032
+ $this->response( preg_replace( '#/.*$#', '', get_option( 'active_plugins' ) ) );
2033
+ break;
2034
+ case 'plugins:checksum': case 'uploads:checksum': case 'themes:checksum': case 'content:checksum': case 'root:checksum':
2035
+ case 'plugins:ls': case 'uploads:ls': case 'themes:ls': case 'content:ls': case 'root:ls':
2036
+ case 'plugins:dir': case 'uploads:dir': case 'themes:dir': case 'content:dir': case 'root:dir':
2037
+ case 'plugins:stat': case 'uploads:stat': case 'themes:stat': case 'content:stat': case 'root:stat':
2038
+ case 'plugins:get': case 'uploads:get': case 'themes:get': case 'content:get': case 'root:get':
2039
+
2040
+ $action_pieces = explode( ':', $_GET['action'] );
2041
+ $bfs->want( array_shift( $action_pieces ) );
2042
+
2043
+ if ( isset( $_POST['path'] ) )
2044
+ $path = $_POST['path'];
2045
+ else
2046
+ $path = '';
2047
+
2048
+ if ( !$bfs->validate( $path ) )
2049
+ die( "naughty naughty" );
2050
+
2051
+ if ( isset( $_POST['sha1'] ) && $_POST['sha1'] )
2052
+ $sha1 = true;
2053
+ else
2054
+ $sha1 = false;
2055
+
2056
+ if ( isset( $_POST['md5'] ) && $_POST['md5'] )
2057
+ $md5 = true;
2058
+ else
2059
+ $md5 = false;
2060
+
2061
+ if ( isset( $_POST['limit'] ) && $_POST['limit'] )
2062
+ $limit=$_POST['limit'];
2063
+ else
2064
+ $limit = false;
2065
+
2066
+ if ( isset( $_POST['offset'] ) && $_POST['offset'] )
2067
+ $offset = $_POST['offset'];
2068
+ else
2069
+ $offset = false;
2070
+
2071
+ if ( isset( $_POST['recursive'] ) )
2072
+ $recursive = (bool)$_POST['recursive'];
2073
+ else
2074
+ $recursive = false;
2075
+
2076
+ if ( isset( $_POST['full_list'] ) )
2077
+ $full_list = (bool)$_POST['full_list'];
2078
+ else
2079
+ $full_list = false;
2080
+
2081
+ $action_pieces = explode( ':', $_GET['action'] );
2082
+ switch ( array_pop( $action_pieces ) ) {
2083
+ default:
2084
+ die( "naughty naughty" );
2085
+ case 'checksum':
2086
+ $list = array();
2087
+ $this->response( $bfs->dir_checksum( $path, $list, $recursive ) );
2088
+ case 'dir':
2089
+ $this->response( $bfs->dir_examine( $path, $recursive ) );
2090
+ case 'stat':
2091
+ $this->response( $bfs->stat( $bfs->dir.$path ) );
2092
+ case 'get':
2093
+ $bfs->fdump( $bfs->dir.$path );
2094
+ case 'ls':
2095
+ $this->response( $bfs->ls( $path, $md5, $sha1, $limit, $offset, $full_list ) );
2096
+ }
2097
+ break;
2098
+ case 'config:get':
2099
+ if ( !isset( $_POST['key'] ) || !$_POST['key'] )
2100
+ $this->response( false );
2101
+ $key = '_vp_config_' . base64_decode( $_POST['key'] );
2102
+ $this->response( base64_encode( maybe_serialize( $this->get_config( $key ) ) ) );
2103
+ break;
2104
+ case 'config:set':
2105
+ if ( !isset( $_POST['key'] ) || !$_POST['key'] ) {
2106
+ $this->response( false );
2107
+ break;
2108
+ }
2109
+ $key = '_vp_config_' . base64_decode( $_POST['key'] );
2110
+ if ( !isset( $_POST['val'] ) || !$_POST['val'] ) {
2111
+ if ( !isset($_POST['delete']) || !$_POST['delete'] ) {
2112
+ $this->response( false );
2113
+ } else {
2114
+ $this->response( delete_option( $key ) );
2115
+ }
2116
+ break;
2117
+ }
2118
+ $val = maybe_unserialize( base64_decode( $_POST['val'] ) );
2119
+ $this->response( update_option( $key, $val ) );
2120
+ break;
2121
+ }
2122
+ die();
2123
+ }
2124
+
2125
+ function _fix_ixr_null_to_string( &$args ) {
2126
+ if ( is_array( $args ) )
2127
+ foreach ( $args as $k => $v )
2128
+ $args[$k] = $this->_fix_ixr_null_to_string( $v );
2129
+ else if ( is_object( $args ) )
2130
+ foreach ( get_object_vars( $args ) as $k => $v )
2131
+ $args->$k = $this->_fix_ixr_null_to_string( $v );
2132
+ else
2133
+ return null == $args ? '' : $args;
2134
+ return $args;
2135
+ }
2136
+
2137
+ function is_localhost() {
2138
+ $site_url = $this->site_url();
2139
+ if ( empty( $site_url ) )
2140
+ return false;
2141
+ $parts = parse_url( $site_url );
2142
+ if ( !empty( $parts['host'] ) && in_array( $parts['host'], array( 'localhost', '127.0.0.1' ) ) )
2143
+ return true;
2144
+ return false;
2145
+ }
2146
+
2147
+ function contact_service( $action, $args = array() ) {
2148
+ if ( 'test' != $action && 'register' != $action && !$this->check_connection() )
2149
+ return false;
2150
+
2151
+ global $current_user;
2152
+ if ( !isset( $args['args'] ) )
2153
+ $args['args'] = '';
2154
+ $old_timeout = ini_get( 'default_socket_timeout' );
2155
+ $timeout = $this->get_option( 'timeout' );
2156
+ if ( function_exists( 'ini_set' ) )
2157
+ ini_set( 'default_socket_timeout', $timeout );
2158
+ $hostname = $this->get_option( 'hostname' );
2159
+
2160
+ if ( !class_exists( 'VaultPress_IXR_SSL_Client' ) )
2161
+ require_once( dirname( __FILE__ ) . '/class.vaultpress-ixr-ssl-client.php' );
2162
+ $useragent = 'VaultPress/' . $this->plugin_version . '; ' . $this->site_url();
2163
+ $client = new VaultPress_IXR_SSL_Client( $hostname, '/xmlrpc.php', 80, $timeout, $useragent );
2164
+
2165
+ if ( 'vaultpress.com' == $hostname )
2166
+ $client->ssl();
2167
+
2168
+ // Begin audit trail breadcrumbs
2169
+ if ( isset( $current_user ) && is_object( $current_user ) && isset( $current_user->ID ) ) {
2170
+ $args['cause_user_id'] = intval( $current_user->ID );
2171
+ $args['cause_user_login'] = (string)$current_user->user_login;
2172
+ } else {
2173
+ $args['cause_user_id'] = -1;
2174
+ $args['cause_user_login'] = '';
2175
+ }
2176
+ $args['cause_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null ;
2177
+ $args['cause_uri'] = isset( $_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null;
2178
+ $args['cause_method'] = isset( $_SERVER['REQUEST_METHOD'] ) ? $_SERVER['REQUEST_METHOD'] : null;
2179
+ // End audit trail breadcrumbs
2180
+
2181
+ $args['version'] = $this->plugin_version;
2182
+ $args['locale'] = get_locale();
2183
+ $args['site_url'] = $this->site_url();
2184
+
2185
+ $salt = md5( time() . serialize( $_SERVER ) );
2186
+ $args['key'] = $this->get_option( 'key' );
2187
+ $this->_fix_ixr_null_to_string( $args );
2188
+ $args['signature'] = $this->sign_string( serialize( $args ), $this->get_option( 'secret' ), $salt ).":$salt";
2189
+
2190
+ $client->query( 'vaultpress.'.$action, new IXR_Base64( serialize( $args ) ) );
2191
+ $rval = $client->message ? $client->getResponse() : '';
2192
+ if ( function_exists( 'ini_set' ) )
2193
+ ini_set( 'default_socket_timeout', $old_timeout );
2194
+
2195
+ // we got an error from the servers
2196
+ if ( is_array( $rval ) && isset( $rval['faultCode'] ) ) {
2197
+ $this->update_option( 'connection', time() );
2198
+ $this->update_option( 'connection_error_code', $rval['faultCode'] );
2199
+ $this->update_option( 'connection_error_message', $rval['faultString'] );
2200
+ }
2201
+
2202
+ return $rval;
2203
+ }
2204
+
2205
+ function validate_api_signature() {
2206
+ global $__vp_validate_error;
2207
+ if ( !empty( $_POST['signature'] ) ) {
2208
+ if ( is_string( $_POST['signature'] ) ) {
2209
+ $sig = $_POST['signature'];
2210
+ } else {
2211
+ $__vp_validate_error = array( 'error' => 'invalid_signature_format' );
2212
+ return false;
2213
+ }
2214
+ } else {
2215
+ $__vp_validate_error = array( 'error' => 'no_signature' );
2216
+ return false;
2217
+ }
2218
+
2219
+ $secret = $this->get_option( 'secret' );
2220
+ if ( !$secret ) {
2221
+ $__vp_validate_error = array( 'error' => 'missing_secret' );
2222
+ return false;
2223
+ }
2224
+ if ( !$this->get_option( 'disable_firewall' ) ) {
2225
+ if ( ! $this->check_firewall() )
2226
+ return false;
2227
+ }
2228
+ $sig = explode( ':', $sig );
2229
+ if ( !is_array( $sig ) || count( $sig ) != 2 || !isset( $sig[0] ) || !isset( $sig[1] ) ) {
2230
+ $__vp_validate_error = array( 'error' => 'invalid_signature_format' );
2231
+ return false;
2232
+ }
2233
+
2234
+ // Pass 1 -- new method
2235
+ $uri = preg_replace( '/^[^?]+\?/', '?', $_SERVER['REQUEST_URI'] );
2236
+ $post = $_POST;
2237
+ unset( $post['signature'] );
2238
+ // Work around for dd-formmailer plugin
2239
+ if ( isset( $post['_REPEATED'] ) )
2240
+ unset( $post['_REPEATED'] );
2241
+ ksort( $post );
2242
+ $to_sign = serialize( array( 'uri' => $uri, 'post' => $post ) );
2243
+
2244
+ if ( $this->can_use_openssl() ) {
2245
+ $sslsig = '';
2246
+ if ( isset( $post['sslsig'] ) ) {
2247
+ $sslsig = $post['sslsig'];
2248
+ unset( $post['sslsig'] );
2249
+ }
2250
+ if ( 1 === openssl_verify( serialize( array( 'uri' => $uri, 'post' => $post ) ), base64_decode( $sslsig ), $this->get_option( 'public_key' ) ) ) {
2251
+ return true;
2252
+ } else {
2253
+ $__vp_validate_error = array( 'error' => 'invalid_signed_data' );
2254
+ return false;
2255
+ }
2256
+ }
2257
+
2258
+ $signature = $this->sign_string( $to_sign, $secret, $sig[1] );
2259
+ if ( hash_equals( $sig[0], $signature ) ) {
2260
+ return true;
2261
+ }
2262
+
2263
+ $__vp_validate_error = array( 'error' => 'invalid_signed_data' );
2264
+ return false;
2265
+ }
2266
+
2267
+ function ip_in_cidr( $ip, $cidr ) {
2268
+ list ($net, $mask) = explode( '/', $cidr );
2269
+ return ( ip2long( $ip ) & ~((1 << (32 - $mask)) - 1) ) == ( ip2long( $net ) & ~((1 << (32 - $mask)) - 1) );
2270
+ }
2271
+
2272
+ function ip_in_cidrs( $ip, $cidrs ) {
2273
+ foreach ( (array)$cidrs as $cidr ) {
2274
+ if ( $this->ip_in_cidr( $ip, $cidr ) ) {
2275
+ return $cidr;
2276
+ }
2277
+ }
2278
+
2279
+ return false;
2280
+ }
2281
+
2282
+ function check_firewall() {
2283
+ global $__vp_validate_error;
2284
+
2285
+ $stored_cidrs = $this->get_option( 'service_ips_cidr' );
2286
+ $stored_ext_cidrs = get_option( 'vaultpress_service_ips_external_cidr' );
2287
+
2288
+ $one_day_ago = time() - 86400;
2289
+ if ( empty( $stored_cidrs ) || empty( $stored_ext_cidrs ) || $stored_cidrs['updated'] < $one_day_ago ) {
2290
+ $cidrs = $this->update_firewall();
2291
+ }
2292
+
2293
+ if ( empty( $cidrs ) ) {
2294
+ $cidrs = array_merge( $stored_cidrs['data'], $stored_ext_cidrs['data'] );
2295
+ }
2296
+
2297
+ if ( empty( $cidrs ) ) {
2298
+ // No up-to-date info; fall back on the old methods.
2299
+ if ( $this->do_c_block_firewall() ) {
2300
+ return true;
2301
+ } else {
2302
+ $__vp_validate_error = array( 'error' => 'empty_vp_ip_cidr_range' );
2303
+ return false;
2304
+ }
2305
+ }
2306
+
2307
+ // Figure out possible remote IPs
2308
+ $remote_ips = array();
2309
+ if ( !empty( $_SERVER['REMOTE_ADDR'] ) )
2310
+ $remote_ips['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
2311
+
2312
+ // If this is a pingback during a connection test, search for valid-looking ips among headers
2313
+ $connection_test_key = $this->get_option( 'connection_test' );
2314
+ $testing_all_headers = ( ! empty( $_POST['test_key'] ) && $_POST['test_key'] === $connection_test_key );
2315
+ if ( $testing_all_headers ) {
2316
+ $remote_ips = array_filter( $_SERVER, array( $this, 'looks_like_ip_list' ) );
2317
+ }
2318
+
2319
+ // If there is a pre-configured forwarding IP header, check that.
2320
+ $forward_header = $this->get_option( 'allow_forwarded_for' );
2321
+ if ( true === $forward_header || 1 == $forward_header ) {
2322
+ $forward_header = 'HTTP_X_FORWARDED_FOR';
2323
+ }
2324
+ if ( ! empty( $forward_header ) && ! empty( $_SERVER[ $forward_header ] ) ) {
2325
+ $remote_ips[ $forward_header ] = $_SERVER[ $forward_header ];
2326
+ }
2327
+
2328
+ if ( empty( $remote_ips ) ) {
2329
+ $__vp_validate_error = array( 'error' => 'no_remote_addr', 'detail' => (int) $this->get_option( 'allow_forwarded_for' ) ); // shouldn't happen
2330
+ return false;
2331
+ }
2332
+
2333
+ foreach ( $remote_ips as $header_name => $ip_list ) {
2334
+ $ips = explode( ',', $ip_list );
2335
+ foreach ( $ips as $ip ) {
2336
+ $ip = preg_replace( '#^::(ffff:)?#', '', $ip );
2337
+ if ( $cidr = $this->ip_in_cidrs( $ip, $cidrs ) ) {
2338
+ // Successful match found. If testing all headers, note the successful header.
2339
+ if ( $testing_all_headers && 'REMOTE_ADDR' !== $header_name ) {
2340
+ $this->update_option( 'allow_forwarded_for', $header_name );
2341
+ }
2342
+
2343
+ return true;
2344
+ }
2345
+ }
2346
+ }
2347
+
2348
+ $__vp_validate_error = array( 'error' => 'remote_addr_fail', 'detail' => $remote_ips );
2349
+ return false;
2350
+ }
2351
+
2352
+ // Returns true if $value looks like a comma-separated list of IPs
2353
+ function looks_like_ip_list( $value ) {
2354
+ if ( ! is_string( $value ) ) {
2355
+ return false;
2356
+ }
2357
+
2358
+ $items = explode( ',', $value );
2359
+ foreach ( $items as $item ) {
2360
+ if ( ip2long( $item ) === false ) {
2361
+ return false;
2362
+ }
2363
+ }
2364
+
2365
+ return true;
2366
+ }
2367
+
2368
+ function do_c_block_firewall() {
2369
+ // Perform the firewall check by class-c ip blocks
2370
+ $rxs = $this->get_option( 'service_ips' );
2371
+ $service_ips_external = get_option( 'vaultpress_service_ips_external' );
2372
+
2373
+ if ( !empty( $rxs['data'] ) && !empty( $service_ips_external['data'] ) )
2374
+ $rxs = array_merge( $rxs['data'], $service_ips_external['data'] );
2375
+ if ( ! $rxs )
2376
+ return false;
2377
+ return $this->validate_ip_address( $rxs );
2378
+ }
2379
+
2380
+ function validate_ip_address( $rxs ) {
2381
+ global $__vp_validate_error;
2382
+ if ( empty( $rxs ) ) {
2383
+ $__vp_validate_error = array( 'error' => 'empty_vp_ip_range' );
2384
+ return false;
2385
+ }
2386
+
2387
+ $remote_ips = array();
2388
+
2389
+ if ( $this->get_option( 'allow_forwarded_for') && !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
2390
+ $remote_ips = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
2391
+
2392
+ if ( !empty( $_SERVER['REMOTE_ADDR'] ) )
2393
+ $remote_ips[] = $_SERVER['REMOTE_ADDR'];
2394
+
2395
+ if ( empty( $remote_ips ) ) {
2396
+ $__vp_validate_error = array( 'error' => 'no_remote_addr', 'detail' => (int) $this->get_option( 'allow_forwarded_for' ) ); // shouldn't happen
2397
+ return false;
2398
+ }
2399
+
2400
+ $iprx = '/^([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/';
2401
+
2402
+ foreach ( $remote_ips as $_remote_ip ) {
2403
+ $remote_ip = preg_replace( '#^::(ffff:)?#', '', $_remote_ip );
2404
+ if ( !preg_match( $iprx, $remote_ip, $r ) ) {
2405
+ $__vp_validate_error = array( 'error' => "remote_addr_fail", 'detail' => $_remote_ip );
2406
+ return false;
2407
+ }
2408
+
2409
+ foreach ( (array)$rxs as $begin => $end ) {
2410
+ if ( !preg_match( $iprx, $begin, $b ) )
2411
+ continue;
2412
+ if ( !preg_match( $iprx, $end, $e ) )
2413
+ continue;
2414
+ if ( $r[1] != $b[1] || $r[1] != $e[1] )
2415
+ continue;
2416
+ $me = $r[2];
2417
+ $b = min( (int)$b[2], (int)$e[2] );
2418
+ $e = max( (int)$b[2], (int)$e[2] );
2419
+ if ( $me >= $b && $me <= $e ) {
2420
+ return true;
2421
+ }
2422
+ }
2423
+ }
2424
+ $__vp_validate_error = array( 'error' => 'remote_addr_fail', 'detail' => $remote_ips );
2425
+
2426
+ return false;
2427
+ }
2428
+
2429
+ function sign_string( $string, $secret, $salt ) {
2430
+ return hash_hmac( 'sha1', "$string:$salt", $secret );
2431
+ }
2432
+
2433
+ function can_use_openssl() {
2434
+ if ( !function_exists( 'openssl_verify' ) )
2435
+ return false;
2436
+ $pk = $this->get_option( 'public_key' );
2437
+ if ( empty( $pk ) )
2438
+ return false;
2439
+ if ( 1 !== (int) $this->get_option( 'use_openssl_signing' ) )
2440
+ return false;
2441
+ return true;
2442
+ }
2443
+
2444
+ function response( $response, $raw = false ) {
2445
+ // "re" -- "Response Encoding"
2446
+ if ( !empty( $_GET['re'] ) )
2447
+ header( sprintf( 'X-VP-Encoded: X%d', abs( intval( $_GET['re'] ) ) ) );
2448
+ if ( $raw ) {
2449
+ if ( !isset( $_GET['re'] ) )
2450
+ die( $response );
2451
+ else if ( '1' === $_GET['re'] )
2452
+ die( base64_encode( $response ) );
2453
+ else if ( '2' === $_GET['re'] )
2454
+ die( str_rot13( $response ) );
2455
+ else
2456
+ die( $response );
2457
+ }
2458
+ list( $usec, $sec ) = explode( " ", microtime() );
2459
+ $r = new stdClass();
2460
+ $r->req_vector = floatval( $_GET['vector'] );
2461
+ $r->rsp_vector = ( (float)$usec + (float)$sec );
2462
+ if ( function_exists( "getrusage" ) )
2463
+ $r->rusage = getrusage();
2464
+ else
2465
+ $r->rusage = false;
2466
+ if ( function_exists( "memory_get_peak_usage" ) )
2467
+ $r->peak_memory_usage = memory_get_peak_usage( true );
2468
+ else
2469
+ $r->peak_memory_usage = false;
2470
+ if ( function_exists( "memory_get_usage" ) )
2471
+ $r->memory_usage = memory_get_usage( true );
2472
+ else
2473
+ $r->memory_usage = false;
2474
+ $r->response = $response;
2475
+ if ( !isset( $_GET['re'] ) )
2476
+ die( serialize( $r ) );
2477
+ else if ( '1' === $_GET['re'] )
2478
+ die( base64_encode( serialize( $r ) ) );
2479
+ else if ( '2' === $_GET['re'] )
2480
+ die( str_rot13( serialize( $r ) ) );
2481
+ else
2482
+ die( serialize( $r ) );
2483
+ }
2484
+
2485
+ function reset_pings() {
2486
+ global $vaultpress_pings;
2487
+ $vaultpress_pings = array(
2488
+ 'version' => 1,
2489
+ 'count' => 0,
2490
+ 'editedtables' => array(),
2491
+ 'plugins' => array(),
2492
+ 'themes' => array(),
2493
+ 'uploads' => array(),
2494
+ 'db' => array(),
2495
+ 'debug' => array(),
2496
+ 'security' => array(),
2497
+ );
2498
+ }
2499
+
2500
+ function add_ping( $type, $data, $hook=null ) {
2501
+ global $vaultpress_pings;
2502
+ if ( defined( 'WP_IMPORTING' ) && constant( 'WP_IMPORTING' ) )
2503
+ return;
2504
+ if ( isset( $_GET ) && isset( $_GET['comment_status'] ) && isset( $_GET['delete_all'] ) && 'spam' == $_GET['comment_status'] )
2505
+ return; // Skip pings from mass spam delete.
2506
+ if ( !array_key_exists( $type, $vaultpress_pings ) )
2507
+ return;
2508
+
2509
+ switch( $type ) {
2510
+ case 'editedtables';
2511
+ $vaultpress_pings[$type] = $data;
2512
+ return;
2513
+ case 'uploads':
2514
+ case 'themes':
2515
+ case 'plugins':
2516
+ if ( !is_array( $data ) ) {
2517
+ $data = array( $data );
2518
+ }
2519
+ foreach ( $data as $val ) {
2520
+ if ( in_array( $data, $vaultpress_pings[$type] ) )
2521
+ continue;
2522
+ $vaultpress_pings['count']++;
2523
+ $vaultpress_pings[$type][]=$val;
2524
+ }
2525
+ return;
2526
+ case 'db':
2527
+ $_keys = array_keys( $data );
2528
+ $subtype = array_shift( $_keys );
2529
+ if ( !isset( $vaultpress_pings[$type][$subtype] ) )
2530
+ $vaultpress_pings[$type][$subtype] = array();
2531
+ if ( in_array( $data, $vaultpress_pings[$type][$subtype] ) )
2532
+ return;
2533
+ $vaultpress_pings['count']++;
2534
+ $vaultpress_pings[$type][$subtype][] = $data;
2535
+ return;
2536
+ default:
2537
+ if ( in_array( $data, $vaultpress_pings[$type] ) )
2538
+ return;
2539
+ $vaultpress_pings['count']++;
2540
+ $vaultpress_pings[$type][] = $data;
2541
+ return;
2542
+ }
2543
+ }
2544
+
2545
+ function do_pings() {
2546
+ global $wpdb, $vaultpress_pings, $__vp_recursive_ping_lock;
2547
+ if ( defined( 'WP_IMPORTING' ) && constant( 'WP_IMPORTING' ) )
2548
+ return;
2549
+
2550
+ if ( !isset( $wpdb ) ) {
2551
+ $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2552
+ $close_wpdb = true;
2553
+ } else {
2554
+ $close_wpdb = false;
2555
+ }
2556
+
2557
+ if ( !$vaultpress_pings['count'] )
2558
+ return;
2559
+
2560
+ // Short circuit the contact process if we know that we can't contact the service
2561
+ if ( isset( $__vp_recursive_ping_lock ) && $__vp_recursive_ping_lock ) {
2562
+ $this->ai_ping_insert( serialize( $vaultpress_pings ) );
2563
+ if ( $close_wpdb ) {
2564
+ $wpdb->__destruct();
2565
+ unset( $wpdb );
2566
+ }
2567
+ $this->reset_pings();
2568
+ return;
2569
+ }
2570
+
2571
+ $ping_attempts = 0;
2572
+ do {
2573
+ $ping_attempts++;
2574
+ $rval = $this->contact_service( 'ping', array( 'args' => $vaultpress_pings ) );
2575
+ if ( $rval || $ping_attempts >= 3 )
2576
+ break;
2577
+ if ( !$rval )
2578
+ usleep(500000);
2579
+ } while ( true );
2580
+ if ( !$rval ) {
2581
+ if ( $this->get_option( 'connection_error_code' ) !== -8 ) { // Do not save pings when the subscription is inactive.
2582
+ $__vp_recursive_ping_lock = true;
2583
+ $this->ai_ping_insert( serialize( $vaultpress_pings ) );
2584
+ }
2585
+ }
2586
+ $this->reset_pings();
2587
+ if ( $close_wpdb ) {
2588
+ $wpdb->__destruct();
2589
+ unset( $wpdb );
2590
+ }
2591
+ return $rval;
2592
+ }
2593
+
2594
+ function resolve_content_dir() {
2595
+ // Take the easy way out
2596
+ if ( defined( 'WP_CONTENT_DIR' ) ) {
2597
+ if ( substr( WP_CONTENT_DIR, -1 ) != DIRECTORY_SEPARATOR )
2598
+ return WP_CONTENT_DIR . DIRECTORY_SEPARATOR;
2599
+ return WP_CONTENT_DIR;
2600
+ }
2601
+ // Best guess
2602
+ if ( defined( 'ABSPATH' ) ) {
2603
+ if ( substr( ABSPATH, -1 ) != DIRECTORY_SEPARATOR )
2604
+ return ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR;
2605
+ return ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR;
2606
+ }
2607
+ // Run with a solid assumption: WP_CONTENT_DIR/vaultpress/vaultpress.php
2608
+ return dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR;
2609
+ }
2610
+
2611
+ function resolve_upload_path() {
2612
+ $upload_path = false;
2613
+ $upload_dir = wp_upload_dir();
2614
+
2615
+ if ( isset( $upload_dir['basedir'] ) )
2616
+ $upload_path = $upload_dir['basedir'];
2617
+
2618
+ // Nothing recorded? use a best guess!
2619
+ if ( !$upload_path || $upload_path == realpath( ABSPATH ) )
2620
+ return $this->resolve_content_dir() . 'uploads' . DIRECTORY_SEPARATOR;
2621
+
2622
+ if ( substr( $upload_path, -1 ) != DIRECTORY_SEPARATOR )
2623
+ $upload_path .= DIRECTORY_SEPARATOR;
2624
+
2625
+ return $upload_path;
2626
+ }
2627
+
2628
+ function load_first( $value ) {
2629
+ $value = array_unique( $value ); // just in case there are duplicates
2630
+ return array_merge(
2631
+ preg_grep( '/vaultpress\.php$/', $value ),
2632
+ preg_grep( '/vaultpress\.php$/', $value, PREG_GREP_INVERT )
2633
+ );
2634
+ }
2635
+
2636
+ function is_multisite() {
2637
+ if ( function_exists( 'is_multisite' ) )
2638
+ return is_multisite();
2639
+
2640
+ return false;
2641
+ }
2642
+
2643
+ function is_main_site() {
2644
+ if ( !function_exists( 'is_main_site' ) || !$this->is_multisite() )
2645
+ return true;
2646
+
2647
+ return is_main_site();
2648
+ }
2649
+
2650
+ function is_registered() {
2651
+ $key = $this->get_option( 'key' );
2652
+ $secret = $this->get_option( 'secret' );
2653
+ return !empty( $key ) && !empty( $secret );
2654
+ }
2655
+
2656
+ function clear_connection() {
2657
+ $this->delete_option( 'connection' );
2658
+ $this->delete_option( 'connection_error_code' );
2659
+ $this->delete_option( 'connection_error_message' );
2660
+ $this->delete_option( 'connection_test' );
2661
+ }
2662
+
2663
+ function site_url() {
2664
+ $site_url = '';
2665
+
2666
+ // compatibility for WordPress MU Domain Mapping plugin
2667
+ if ( defined( 'DOMAIN_MAPPING' ) && DOMAIN_MAPPING && ! function_exists( 'domain_mapping_siteurl' ) ) {
2668
+ if ( !function_exists( 'is_plugin_active' ) )
2669
+ require_once ABSPATH . '/wp-admin/includes/plugin.php';
2670
+
2671
+ $plugin = 'wordpress-mu-domain-mapping/domain_mapping.php';
2672
+ if ( is_plugin_active( $plugin ) )
2673
+ include_once( WP_PLUGIN_DIR . '/' . $plugin );
2674
+ }
2675
+
2676
+ if ( function_exists( 'domain_mapping_siteurl' ) )
2677
+ $site_url = domain_mapping_siteurl( false );
2678
+
2679
+ if ( empty( $site_url ) )
2680
+ $site_url = site_url();
2681
+
2682
+ return $site_url;
2683
+ }
2684
+
2685
+ /**
2686
+ * Sync the VaultPress options to WordPress.com if the Jetpack plugin is active.
2687
+ */
2688
+ function sync_jetpack_options() {
2689
+ if ( class_exists( 'Jetpack_Sync' ) && method_exists( 'Jetpack_Sync', 'sync_options' ) && defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '4.1', '<' ) ) {
2690
+ Jetpack_Sync::sync_options( __FILE__, $this->auto_register_option, $this->option_name );
2691
+ }
2692
+ }
2693
+
2694
+ /**
2695
+ * Add the VaultPress options to the Jetpack options management whitelist.
2696
+ * Allows Jetpack to register VaultPress options automatically.
2697
+ *
2698
+ * @param array $options The list of whitelisted option names.
2699
+ *
2700
+ * @return array The updated whitelist
2701
+ */
2702
+ function add_to_jetpack_options_whitelist( $options ) {
2703
+ $options[] = $this->option_name;
2704
+ $options[] = $this->auto_register_option;
2705
+
2706
+ return $options;
2707
+ }
2708
+
2709
+ /**
2710
+ * When the VaultPress auto-register option is updated, run the registration call.
2711
+ *
2712
+ * This should only be run when the option is updated from the Jetpack/WP.com
2713
+ * API call, and only if the new key is different than the old key.
2714
+ *
2715
+ * @param mixed $old_value The old option value, or the option name (if add_option).
2716
+ * @param mixed $value The new option value.
2717
+ */
2718
+ function updated_auto_register_option( $old_value, $value ) {
2719
+ // Not an API call or CLI call
2720
+ if ( ! class_exists( 'WPCOM_JSON_API_Update_Option_Endpoint' ) && ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
2721
+ return;
2722
+ }
2723
+
2724
+ remove_action( "update_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ) );
2725
+
2726
+ $defaults = array(
2727
+ 'key' => false,
2728
+ 'action' => 'register', // or `response`
2729
+ 'status' => 'working',
2730
+ 'error' => false,
2731
+ );
2732
+
2733
+ // `wp_parse_args` uses arrays, might as well be explicit about it.
2734
+ $registration = (array) json_decode( $value );
2735
+ $registration = wp_parse_args( $registration, $defaults );
2736
+
2737
+ // If we have a working connection, don't update the key.
2738
+ if ( $this->check_connection( true ) ) {
2739
+ $registration['action'] = 'response';
2740
+ $registration['error'] = 'VaultPress is already registered on this site.';
2741
+ update_option( $this->auto_register_option, json_encode( $registration ) );
2742
+ return;
2743
+ }
2744
+
2745
+ if ( ! $registration['key'] ) {
2746
+ return;
2747
+ }
2748
+
2749
+ $registration['action'] = 'response';
2750
+
2751
+ $response = $this->register( $registration['key'] );
2752
+ if ( is_wp_error( $response ) ) {
2753
+ $registration['status'] = 'broken';
2754
+ $registration['error'] = $response->get_error_message();
2755
+ } else if ( $this->get_option( 'connection_error_code' ) ) {
2756
+ $registration['status'] = 'broken';
2757
+ $registration['error'] = $this->get_option( 'connection_error_message' );
2758
+ } else {
2759
+ $registration['error'] = false;
2760
+ }
2761
+
2762
+ update_option( $this->auto_register_option, json_encode( $registration ) );
2763
+ }
2764
+
2765
+ function add_global_actions_and_filters() {
2766
+ add_action( 'init', array( $this, 'sync_jetpack_options' ), 0, 99 );
2767
+ add_filter( 'jetpack_options_whitelist', array( $this, 'add_to_jetpack_options_whitelist' ) );
2768
+ add_action( "update_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ), 10, 2 );
2769
+ add_action( "add_option_{$this->auto_register_option}", array( $this, 'updated_auto_register_option' ), 10, 2 );
2770
+ add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
2771
+ }
2772
+
2773
+ function add_admin_actions_and_filters() {
2774
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
2775
+ add_action( 'admin_menu', array( $this, 'admin_menu' ), 5 ); # Priority 5, so it's called before Jetpack's admin_menu.
2776
+ add_action( 'admin_head', array( $this, 'admin_head' ) );
2777
+ }
2778
+
2779
+ function add_listener_actions_and_filters() {
2780
+ add_action( 'admin_bar_menu', array( $this, 'toolbar' ), 999 );
2781
+
2782
+ // Comments
2783
+ add_action( 'delete_comment', array( $this, 'comment_action_handler' ) );
2784
+ add_action( 'wp_set_comment_status', array( $this, 'comment_action_handler' ) );
2785
+ add_action( 'trashed_comment', array( $this, 'comment_action_handler' ) );
2786
+ add_action( 'untrashed_comment', array( $this, 'comment_action_handler' ) );
2787
+ add_action( 'wp_insert_comment', array( $this, 'comment_action_handler' ) );
2788
+ add_action( 'comment_post', array( $this, 'comment_action_handler' ) );
2789
+ add_action( 'edit_comment', array( $this, 'comment_action_handler' ) );
2790
+
2791
+ // Commentmeta
2792
+ add_action( 'added_comment_meta', array( $this, 'commentmeta_insert_handler' ), 10, 2 );
2793
+ add_action( 'updated_comment_meta', array( $this, 'commentmeta_modification_handler' ), 10, 4 );
2794
+ add_action( 'deleted_comment_meta', array( $this, 'commentmeta_modification_handler' ), 10, 4 );
2795
+
2796
+ // Users
2797
+ if ( $this->is_main_site() ) {
2798
+ add_action( 'user_register', array( $this, 'userid_action_handler' ) );
2799
+ add_action( 'password_reset', array( $this, 'userid_action_handler' ) );
2800
+ add_action( 'profile_update', array( $this, 'userid_action_handler' ) );
2801
+ add_action( 'user_register', array( $this, 'userid_action_handler' ) );
2802
+ add_action( 'deleted_user', array( $this, 'userid_action_handler' ) );
2803
+ }
2804
+
2805
+ // Usermeta
2806
+ if ( $this->is_main_site() ) {
2807
+ add_action( 'added_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2808
+ add_action( 'update_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2809
+ add_action( 'delete_usermeta', array( $this, 'usermeta_action_handler' ), 10, 4 );
2810
+ }
2811
+
2812
+ // Posts
2813
+ add_action( 'delete_post', array( $this, 'post_action_handler' ) );
2814
+ add_action( 'trash_post', array( $this, 'post_action_handler' ) );
2815
+ add_action( 'untrash_post', array( $this, 'post_action_handler' ) );
2816
+ add_action( 'edit_post', array( $this, 'post_action_handler' ) );
2817
+ add_action( 'save_post', array( $this, 'post_action_handler' ) );
2818
+ add_action( 'wp_insert_post', array( $this, 'post_action_handler' ) );
2819
+ add_action( 'edit_attachment', array( $this, 'post_action_handler' ) );
2820
+ add_action( 'add_attachment', array( $this, 'post_action_handler' ) );
2821
+ add_action( 'delete_attachment', array( $this, 'post_action_handler' ) );
2822
+ add_action( 'private_to_published', array( $this, 'post_action_handler' ) );
2823
+ add_action( 'wp_restore_post_revision', array( $this, 'post_action_handler' ) );
2824
+
2825
+ // Postmeta
2826
+ add_action( 'added_post_meta', array( $this, 'postmeta_insert_handler' ), 10, 4 );
2827
+ add_action( 'update_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2828
+ add_action( 'updated_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2829
+ add_action( 'delete_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2830
+ add_action( 'deleted_post_meta', array( $this, 'postmeta_modification_handler' ), 10, 4 );
2831
+ add_action( 'added_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2832
+ add_action( 'update_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2833
+ add_action( 'delete_postmeta', array( $this, 'postmeta_action_handler' ), 10, 3 );
2834
+
2835
+ // Links
2836
+ add_action( 'edit_link', array( $this, 'link_action_handler' ) );
2837
+ add_action( 'add_link', array( $this, 'link_action_handler' ) );
2838
+ add_action( 'delete_link', array( $this, 'link_action_handler' ) );
2839
+
2840
+ // Taxonomy
2841
+ add_action( 'created_term', array( $this, 'term_handler' ), 2 );
2842
+ add_action( 'edited_terms', array( $this, 'term_handler' ), 2 );
2843
+ add_action( 'delete_term', array( $this, 'term_handler' ), 2 );
2844
+ add_action( 'edit_term_taxonomy', array( $this, 'term_taxonomy_handler' ) );
2845
+ add_action( 'delete_term_taxonomy', array( $this, 'term_taxonomy_handler' ) );
2846
+ add_action( 'edit_term_taxonomies', array( $this, 'term_taxonomies_handler' ) );
2847
+ add_action( 'add_term_relationship', array( $this, 'term_relationship_handler' ), 10, 2 );
2848
+ add_action( 'delete_term_relationships', array( $this, 'term_relationships_handler' ), 10, 2 );
2849
+ add_action( 'set_object_terms', array( $this, 'set_object_terms_handler' ), 10, 3 );
2850
+
2851
+ // Files
2852
+ if ( $this->is_main_site() ) {
2853
+ add_action( 'switch_theme', array( $this, 'theme_action_handler' ) );
2854
+ add_action( 'activate_plugin', array( $this, 'plugin_action_handler' ) );
2855
+ add_action( 'deactivate_plugin', array( $this, 'plugin_action_handler' ) );
2856
+ }
2857
+ add_action( 'wp_handle_upload', array( $this, 'upload_handler' ) );
2858
+
2859
+ // Options
2860
+ add_action( 'deleted_option', array( $this, 'option_handler' ), 1 );
2861
+ add_action( 'updated_option', array( $this, 'option_handler' ), 1 );
2862
+ add_action( 'added_option', array( $this, 'option_handler' ), 1 );
2863
+
2864
+ $this->add_woocommerce_actions();
2865
+ $this->add_vp_required_filters();
2866
+ }
2867
+
2868
+ function add_woocommerce_actions() {
2869
+ add_action( 'woocommerce_tax_rate_deleted', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2870
+ add_action( 'woocommerce_tax_rate_updated', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2871
+ add_action( 'woocommerce_tax_rate_added', array( $this, 'woocommerce_tax_rate_handler' ), 10, 1 );
2872
+
2873
+ add_action( 'woocommerce_new_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2874
+ add_action( 'woocommerce_update_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2875
+ add_action( 'woocommerce_delete_order_item', array( $this, 'woocommerce_order_item_handler' ), 10, 1 );
2876
+
2877
+ add_action( 'added_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2878
+ add_action( 'updated_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2879
+ add_action( 'deleted_order_item_meta', array( $this, 'woocommerce_order_item_meta_handler' ), 10, 1 );
2880
+
2881
+ add_action( 'woocommerce_attribute_added', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2882
+ add_action( 'woocommerce_attribute_updated', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2883
+ add_action( 'woocommerce_attribute_deleted', array( $this, 'woocommerce_attribute_handler' ), 10, 1 );
2884
+ }
2885
+
2886
+ function add_vp_required_filters() {
2887
+ // Log ins
2888
+ if ( $this->get_option( 'login_lockdown' ) ) {
2889
+ add_action( 'login_form', array( $this, 'add_js_token' ) );
2890
+ add_filter( 'authenticate', array( $this, 'authenticate' ), 999 );
2891
+ }
2892
+
2893
+ // Report back to VaultPress
2894
+ add_action( 'shutdown', array( $this, 'do_pings' ) );
2895
+
2896
+ // VaultPress likes being first in line
2897
+ add_filter( 'pre_update_option_active_plugins', array( $this, 'load_first' ) );
2898
+ }
2899
+
2900
+ function get_jetpack_email() {
2901
+ if ( !class_exists('Jetpack') )
2902
+ return false;
2903
+
2904
+ Jetpack::load_xml_rpc_client();
2905
+ $xml = new Jetpack_IXR_Client( array( 'user_id' => get_current_user_id() ) );
2906
+ $xml->query( 'wpcom.getUserEmail' );
2907
+ if ( ! $xml->isError() ) {
2908
+ return $xml->getResponse();
2909
+ }
2910
+
2911
+ return new WP_Error( $xml->getErrorCode(), $xml->getErrorMessage() );
2912
+ }
2913
+
2914
+ function get_key_via_jetpack( $already_purchased = false ) {
2915
+ if ( !class_exists('Jetpack') )
2916
+ return false;
2917
+
2918
+ Jetpack::load_xml_rpc_client();
2919
+ $xml = new Jetpack_IXR_Client( array( 'user_id' => Jetpack_Options::get_option( 'master_user' ) ) );
2920
+ $xml->query( 'vaultpress.registerSite', $already_purchased );
2921
+ if ( ! $xml->isError() ) {
2922
+ return $xml->getResponse();
2923
+ }
2924
+
2925
+ return new WP_Error( $xml->getErrorCode(), $xml->getErrorMessage() );
2926
+ }
2927
+
2928
+ function register_via_jetpack( $already_purchased = false ) {
2929
+ $registration_key = $this->get_key_via_jetpack( $already_purchased );
2930
+ if ( is_wp_error( $registration_key ) ) {
2931
+ return $registration_key;
2932
+ }
2933
+
2934
+ return self::register( $registration_key );
2935
+ }
2936
+ }
2937
+
2938
  $vaultpress = VaultPress::init();
2939
 
2940
  if ( isset( $_GET['vaultpress'] ) && $_GET['vaultpress'] ) {
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit3a75cf5e3a8a600ae6ae79f2b0d1d6de::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit1c78c6262c4d1a476495a63729d12950::getLoader();
vendor/autoload_packages.php CHANGED
@@ -120,10 +120,10 @@ if ( ! function_exists( __NAMESPACE__ . '\autoloader' ) ) {
120
  /**
121
  * Prepare all the classes for autoloading.
122
  */
123
- function enqueue_packages_6d59d070f6e47eeebec97f53b0905662() {
124
  $class_map = require_once dirname( __FILE__ ) . '/composer/autoload_classmap_package.php';
125
  foreach ( $class_map as $class_name => $class_info ) {
126
  enqueue_package_class( $class_name, $class_info['version'], $class_info['path'] );
127
  }
128
  }
129
- enqueue_packages_6d59d070f6e47eeebec97f53b0905662();
120
  /**
121
  * Prepare all the classes for autoloading.
122
  */
123
+ function enqueue_packages_64aab6881503fadc5588f7415d499df6() {
124
  $class_map = require_once dirname( __FILE__ ) . '/composer/autoload_classmap_package.php';
125
  foreach ( $class_map as $class_name => $class_info ) {
126
  enqueue_package_class( $class_name, $class_info['version'], $class_info['path'] );
127
  }
128
  }
129
+ enqueue_packages_64aab6881503fadc5588f7415d499df6();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit3a75cf5e3a8a600ae6ae79f2b0d1d6de
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit3a75cf5e3a8a600ae6ae79f2b0d1d6de
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit3a75cf5e3a8a600ae6ae79f2b0d1d6de', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit3a75cf5e3a8a600ae6ae79f2b0d1d6de', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit3a75cf5e3a8a600ae6ae79f2b0d1d6de::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit1c78c6262c4d1a476495a63729d12950
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit1c78c6262c4d1a476495a63729d12950', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit1c78c6262c4d1a476495a63729d12950', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit1c78c6262c4d1a476495a63729d12950::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit3a75cf5e3a8a600ae6ae79f2b0d1d6de
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'V' =>
@@ -49,8 +49,8 @@ class ComposerStaticInit3a75cf5e3a8a600ae6ae79f2b0d1d6de
49
  public static function getInitializer(ClassLoader $loader)
50
  {
51
  return \Closure::bind(function () use ($loader) {
52
- $loader->prefixLengthsPsr4 = ComposerStaticInit3a75cf5e3a8a600ae6ae79f2b0d1d6de::$prefixLengthsPsr4;
53
- $loader->prefixDirsPsr4 = ComposerStaticInit3a75cf5e3a8a600ae6ae79f2b0d1d6de::$prefixDirsPsr4;
54
 
55
  }, null, ClassLoader::class);
56
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit1c78c6262c4d1a476495a63729d12950
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'V' =>
49
  public static function getInitializer(ClassLoader $loader)
50
  {
51
  return \Closure::bind(function () use ($loader) {
52
+ $loader->prefixLengthsPsr4 = ComposerStaticInit1c78c6262c4d1a476495a63729d12950::$prefixLengthsPsr4;
53
+ $loader->prefixDirsPsr4 = ComposerStaticInit1c78c6262c4d1a476495a63729d12950::$prefixDirsPsr4;
54
 
55
  }, null, ClassLoader::class);
56
  }