ManageWP Worker - Version 3.9.23

Version Description

  • New: SEO reports can be branded and viewed by sharing an URL
  • New: Set custom database prefix for new clone destination
  • New: Automatic change all URL paths for new clone destination
  • New: Success and fail email notifications for scheduled backup tasks
  • Fix: Improved scheduled backups for limited server resources
  • Fix: Improved backup to Dropbox (now supporting larger backup files)
  • Fix: Handling of external images with bulk posting
  • Fix: Display plugin versions on manage plugins
  • Fix: Deprecated get_themes function
  • Fix: Special characters support for notes
Download this release

Release Info

Developer freediver
Plugin Icon 128x128 ManageWP Worker
Version 3.9.23
Comparing to
See all releases

Code changes from version 3.9.22 to 3.9.23

Files changed (10) hide show
  1. backup.class.php +1402 -831
  2. core.class.php +1 -0
  3. helper.class.php +21 -5
  4. init.php +49 -12
  5. installer.class.php +169 -79
  6. lib/dropbox.oauth.php +0 -1134
  7. lib/dropbox.php +275 -136
  8. post.class.php +748 -745
  9. readme.txt +13 -1
  10. version +1 -1
backup.class.php CHANGED
@@ -16,7 +16,7 @@ endif;
16
  define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
17
  define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
18
 
19
- $zip_errors = array(
20
  'No error',
21
  'No error',
22
  'Unexpected end of zip file',
@@ -57,9 +57,16 @@ $unzip_errors = array(
57
  82 => 'No files were found due to bad decryption password(s)'
58
  );
59
 
60
-
61
- class MMB_Backup extends MMB_Core
62
- {
 
 
 
 
 
 
 
63
  var $site_name;
64
  var $statuses;
65
  var $tasks;
@@ -67,8 +74,13 @@ class MMB_Backup extends MMB_Core
67
  var $ftp;
68
  var $dropbox;
69
  var $google_drive;
70
- function __construct()
71
- {
 
 
 
 
 
72
  parent::__construct();
73
  $this->site_name = str_replace(array(
74
  "_",
@@ -93,13 +105,17 @@ class MMB_Backup extends MMB_Core
93
  $this->tasks = get_option('mwp_backup_tasks');
94
  }
95
 
96
- function set_memory()
97
- {
 
 
 
 
98
  $changed = array('execution_time' => 0, 'memory_limit' => 0);
99
 
100
  $memory_limit = trim(ini_get('memory_limit'));
101
  $last = strtolower(substr($memory_limit, -1));
102
-
103
  if($last == 'g')
104
  $memory_limit = ((int) $memory_limit)*1024;
105
  else if($last == 'm')
@@ -108,21 +124,24 @@ class MMB_Backup extends MMB_Core
108
  $memory_limit = ((int) $memory_limit)/1024;
109
 
110
  if ( $memory_limit < 384 ) {
111
- @ini_set('memory_limit', '384M');
112
- $changed['memory_limit'] = 1;
113
- }
114
-
115
- if ( (int) @ini_get('max_execution_time') < 600 ) {
116
- @set_time_limit(600); //ten minutes
117
  $changed['execution_time'] = 1;
118
  }
119
 
120
  return $changed;
121
-
122
  }
123
 
124
- function get_backup_settings()
125
- {
 
 
 
 
126
  $backup_settings = get_option('mwp_backup_tasks');
127
 
128
  if (!empty($backup_settings))
@@ -131,18 +150,23 @@ class MMB_Backup extends MMB_Core
131
  return false;
132
  }
133
 
134
- function set_backup_task($params)
135
- {
 
 
 
 
 
136
  //$params => [$task_name, $args, $error]
137
  if (!empty($params)) {
138
-
139
  //Make sure backup cron job is set
140
- if (!wp_next_scheduled('mwp_backup_tasks')) {
141
- wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
142
- }
143
 
144
  extract($params);
145
-
146
  //$before = $this->get_backup_settings();
147
  $before = $this->tasks;
148
  if (!$before || empty($before))
@@ -185,11 +209,11 @@ class MMB_Backup extends MMB_Core
185
  //update_option('mwp_backup_tasks', $before);
186
 
187
  if ($task_name == 'Backup Now') {
188
- $result = $this->backup($args, $task_name);
189
  $backup_settings = $this->tasks;
190
 
191
  if (is_array($result) && array_key_exists('error', $result)) {
192
- $return = $result;
193
  } else {
194
  $return = $backup_settings[$task_name];
195
  }
@@ -197,15 +221,19 @@ class MMB_Backup extends MMB_Core
197
  return $return;
198
  }
199
 
200
-
201
-
202
  return false;
203
  }
204
 
205
- //Cron check
 
 
 
 
 
206
  function check_backup_tasks() {
207
  $this->check_cron_remove();
208
 
 
209
  $settings = $this->tasks;
210
  if (is_array($settings) && !empty($settings)) {
211
  foreach ($settings as $task_name => $setting) {
@@ -216,7 +244,8 @@ class MMB_Backup extends MMB_Core
216
  $check_data = array(
217
  'task_name' => $task_name,
218
  'task_id' => $setting['task_args']['task_id'],
219
- 'site_key' => $setting['task_args']['site_key']
 
220
  );
221
 
222
  if (isset($setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'])) {
@@ -224,22 +253,31 @@ class MMB_Backup extends MMB_Core
224
  }
225
 
226
  $check = $this->validate_task($check_data, $setting['task_args']['url']);
 
227
 
228
- $potential_token = substr($check, 8);
229
- if (substr($check, 0, 8) == 'token - ' && $potential_token != 'not found') {
230
- $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
231
- $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
232
- $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
 
 
 
 
 
 
 
 
 
233
  }
234
 
235
  }
236
-
237
  $update = array(
238
  'task_name' => $task_name,
239
  'args' => $settings[$task_name]['task_args']
240
  );
241
 
242
-
243
  if($check != 'paused'){
244
  $update['time'] = time();
245
  }
@@ -262,7 +300,29 @@ class MMB_Backup extends MMB_Core
262
  'error' => $error
263
  ));
264
  } else {
265
- $error = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  }
267
 
268
  break; //Only one backup per cron
@@ -272,7 +332,14 @@ class MMB_Backup extends MMB_Core
272
 
273
  }
274
 
275
- function task_now($task_name, $google_drive_token = false){
 
 
 
 
 
 
 
276
  if ($google_drive_token) {
277
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
278
  }
@@ -283,7 +350,7 @@ class MMB_Backup extends MMB_Core
283
  } else {
284
  $setting = $settings[$task_name];
285
  }
286
-
287
  $this->set_backup_task(array(
288
  'task_name' => $task_name,
289
  'args' => $settings[$task_name]['task_args'],
@@ -306,36 +373,38 @@ class MMB_Backup extends MMB_Core
306
  }
307
  }
308
 
309
-
310
-
311
- /*
312
- * If Task Name not set then it's manual backup
313
- * Backup args:
314
- * type -> db, full
315
- * what -> daily, weekly, monthly
316
- * account_info -> ftp, amazons3, dropbox, google_drive, email
317
- * exclude-> array of paths to exclude from backup
 
 
 
318
  */
319
-
320
  function backup($args, $task_name = false) {
321
  if (!$args || empty($args))
322
  return false;
323
 
324
  extract($args); //extract settings
325
 
326
- if (!empty($account_info))
327
- {
328
- $found = false;
329
- $destinations = array('mwp_ftp', 'mwp_amazon_s3', 'mwp_dropbox', 'mwp_google_drive', 'mwp_email');
330
- foreach($destinations as $dest) {
331
- $found = $found || (isset($account_info[$dest]));
332
- }
333
- if (!$found) {
334
- return array(
335
- 'error' => 'Remote destination is not supported, please update your client plugin.'
336
- );
337
- }
338
- }
339
 
340
  //Try increase memory limit and execution time
341
  $this->set_memory();
@@ -343,6 +412,7 @@ class MMB_Backup extends MMB_Core
343
  //Remove old backup(s)
344
  $removed = $this->remove_old_backups($task_name);
345
  if (is_array($removed) && isset($removed['error'])) {
 
346
  return $removed;
347
  }
348
 
@@ -350,111 +420,75 @@ class MMB_Backup extends MMB_Core
350
 
351
  if (!file_exists($new_file_path)) {
352
  if (!mkdir($new_file_path, 0755, true))
353
- return array(
354
- 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
355
- );
 
356
  }
357
 
358
  @file_put_contents($new_file_path . '/index.php', ''); //safe
359
-
360
  //Prepare .zip file name
361
  $hash = md5(time());
362
  $label = $type ? $type : 'manual';
363
  $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
364
  $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
365
 
 
 
366
  //Optimize tables?
367
  if (isset($optimize_tables) && !empty($optimize_tables)) {
368
  $this->optimize_tables();
369
  }
370
-
371
  //What to backup - db or full?
372
  if (trim($what) == 'db') {
373
- //Take database backup
374
- $this->update_status($task_name, $this->statuses['db_dump']);
375
- $db_result = $this->backup_db();
376
- if ($db_result == false) {
377
- return array(
378
- 'error' => 'Failed to backup database.'
379
- );
380
- } else if (is_array($db_result) && isset($db_result['error'])) {
381
- return array(
382
- 'error' => $db_result['error']
383
- );
384
- } else {
385
- $this->update_status($task_name, $this->statuses['db_dump'], true);
386
- $this->update_status($task_name, $this->statuses['db_zip']);
387
-
388
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
389
- $comp_level = $disable_comp ? '-0' : '-1';
390
-
391
- @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
392
- chdir(MWP_BACKUP_DIR);
393
- $zip = $this->get_zip();
394
- $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
395
- ob_start();
396
- $result = $this->mmb_exec($command);
397
- ob_get_clean();
398
-
399
- if (!$result) { // fallback to pclzip
400
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
401
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
402
- $archive = new PclZip($backup_file);
403
- if ($disable_comp) {
404
- $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
405
- } else {
406
- $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
407
- }
408
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
409
- @unlink($db_result);
410
- @rmdir(MWP_DB_DIR);
411
-
412
- if (!$result) {
413
- return array(
414
- 'error' => 'Failed to zip database (pclZip - ' . $archive->error_code . '): .' . $archive->error_string
415
- );
416
- }
417
- }
418
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
419
- @unlink($db_result);
420
- @rmdir(MWP_DB_DIR);
421
-
422
- if (!$result) {
423
- return array(
424
- 'error' => 'Failed to zip database.'
425
- );
426
- }
427
- $this->update_status($task_name, $this->statuses['db_zip'], true);
428
  }
429
  } elseif (trim($what) == 'full') {
430
- $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
 
 
 
 
 
 
431
  if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
432
- return array(
433
- 'error' => $content_backup['error']
 
434
  );
435
  }
436
  }
437
 
 
 
438
  //Update backup info
439
  if ($task_name) {
440
  //backup task (scheduled)
441
  $backup_settings = $this->tasks;
442
  $paths = array();
443
  $size = ceil(filesize($backup_file) / 1024);
 
444
 
445
  if ($size > 1000) {
446
- $paths['size'] = ceil($size / 1024) . "Mb";
447
  } else {
448
  $paths['size'] = $size . 'kb';
449
  }
450
 
 
 
451
  if ($task_name != 'Backup Now') {
452
- if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
453
- $paths['server'] = array(
454
- 'file_path' => $backup_file,
455
- 'file_url' => $backup_url
456
- );
457
- }
458
  } else {
459
  $paths['server'] = array(
460
  'file_path' => $backup_file,
@@ -499,99 +533,26 @@ class MMB_Backup extends MMB_Core
499
  //update_option('mwp_backup_tasks', $backup_settings);
500
  }
501
 
 
 
 
 
502
 
503
- //Additional: Email, ftp, amazon_s3, google_drive, ...
504
-
505
- if ($task_name != 'Backup Now') {
506
- if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
507
- $this->update_status($task_name, $this->statuses['ftp']);
508
- $account_info['mwp_ftp']['backup_file'] = $backup_file;
509
- $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
510
-
511
- if ($ftp_result !== true && $del_host_file) {
512
- @unlink($backup_file);
513
- }
514
-
515
- if (is_array($ftp_result) && isset($ftp_result['error'])) {
516
- return $ftp_result;
517
- }
518
- $this->wpdb_reconnect();
519
- $this->update_status($task_name, $this->statuses['ftp'], true);
520
- }
521
-
522
- if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
523
- $this->update_status($task_name, $this->statuses['s3']);
524
- $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
525
- $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
526
- if ($amazons3_result !== true && $del_host_file) {
527
- @unlink($backup_file);
528
- }
529
- if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
530
- return $amazons3_result;
531
- }
532
- $this->wpdb_reconnect();
533
- $this->update_status($task_name, $this->statuses['s3'], true);
534
- }
535
-
536
- if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
537
- $this->update_status($task_name, $this->statuses['dropbox']);
538
- $account_info['mwp_dropbox']['backup_file'] = $backup_file;
539
- $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
540
- if ($dropbox_result !== true && $del_host_file) {
541
- @unlink($backup_file);
542
- }
543
-
544
- if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
545
- return $dropbox_result;
546
- }
547
- $this->wpdb_reconnect();
548
- $this->update_status($task_name, $this->statuses['dropbox'], true);
549
- }
550
-
551
- if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
552
- $this->update_status($task_name, $this->statuses['email']);
553
- $account_info['mwp_email']['task_name'] = $task_name;
554
- $account_info['mwp_email']['file_path'] = $backup_file;
555
-
556
- $email_result = $this->email_backup($account_info['mwp_email']);
557
- if (is_array($email_result) && isset($email_result['error'])) {
558
- return $email_result;
559
- }
560
- $this->update_status($task_name, $this->statuses['email'], true);
561
- }
562
-
563
- if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
564
- $this->update_status($task_name, $this->statuses['google_drive']);
565
- $account_info['mwp_google_drive']['backup_file'] = $backup_file;
566
- $google_drive_result = $this->google_drive_backup($account_info['mwp_google_drive']);
567
- if ($google_drive_result !== true && $del_host_file) {
568
- @unlink($backup_file);
569
- }
570
- if (is_array($google_drive_result) && isset($google_drive_result['error'])) {
571
- return $google_drive_result;
572
- }
573
- $this->wpdb_reconnect();
574
- $this->update_status($task_name, $this->statuses['google_drive'], true);
575
- }
576
-
577
- if ($del_host_file) {
578
- @unlink($backup_file);
579
- }
580
-
581
-
582
-
583
- } //end additional
584
-
585
- //$this->update_status($task_name,$this->statuses['finished'],true);
586
- return $backup_url; //Return url to backup file
587
  }
588
 
589
- function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
590
- {
591
- global $zip_errors;
592
- $sys = substr(PHP_OS, 0, 3);
593
-
594
- $this->update_status($task_name, $this->statuses['db_dump']);
 
 
 
 
 
 
595
  $db_result = $this->backup_db();
596
 
597
  if ($db_result == false) {
@@ -605,210 +566,75 @@ class MMB_Backup extends MMB_Core
605
  }
606
 
607
  $this->update_status($task_name, $this->statuses['db_dump'], true);
608
- $this->update_status($task_name, $this->statuses['db_zip']);
609
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
610
- $comp_level = $disable_comp ? '-0' : '-1';
611
- @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
612
- $zip = $this->get_zip();
613
- //Add database file
614
- chdir(MWP_BACKUP_DIR);
615
- $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
616
- ob_start();
617
- $result = $this->mmb_exec($command);
618
- ob_get_clean();
619
-
620
 
621
- if (!$result) {
622
- $this->_log("DB zip fallback to pclZip");
623
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
624
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
625
- $archive = new PclZip($backup_file);
626
-
627
- if ($disable_comp) {
628
- $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
629
- } else {
630
- $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
631
- }
632
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
633
- @unlink($db_result);
634
- @rmdir(MWP_DB_DIR);
635
-
636
- if (!$result_db) {
637
- return array(
638
- 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
639
- );
640
- }
 
 
 
641
  }
 
642
  @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
643
  @unlink($db_result);
644
  @rmdir(MWP_DB_DIR);
645
 
646
- $this->update_status($task_name, $this->statuses['db_zip'], true);
647
-
648
-
649
- //Always remove backup folders
650
  $remove = array(
651
- trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
652
- trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
653
  );
 
654
 
655
- //Exclude paths
656
- $exclude_data = "-x";
657
-
658
- $exclude_file_data = '';
659
-
660
- if (!empty($exclude)) {
661
- foreach ($exclude as $data) {
662
- if (is_dir(ABSPATH . $data)) {
663
- if ($sys == 'WIN')
664
- $exclude_data .= " $data/*.*";
665
- else
666
- $exclude_data .= " '$data/*'";
667
-
668
-
669
- } else {
670
- if ($sys == 'WIN'){
671
- if(file_exists(ABSPATH . $data)){
672
- $exclude_data .= " $data";
673
- $exclude_file_data .= " $data";
674
- }
675
- } else {
676
- if(file_exists(ABSPATH . $data)){
677
- $exclude_data .= " '$data'";
678
- $exclude_file_data .= " '$data'";
679
- }
680
- }
681
- }
682
- }
683
- }
684
-
685
- if($exclude_file_data){
686
- $exclude_file_data = "-x".$exclude_file_data;
687
- }
688
-
689
- foreach ($remove as $data) {
690
- if ($sys == 'WIN')
691
- $exclude_data .= " $data/*.*";
692
- else
693
- $exclude_data .= " '$data/*'";
694
- }
695
-
696
- //Include paths by default
697
- $add = array(
698
- trim(WPINC),
699
- trim(basename(WP_CONTENT_DIR)),
700
- "wp-admin"
701
- );
702
-
703
- $include_data = ". -i";
704
- foreach ($add as $data) {
705
- if ($sys == 'WIN')
706
- $include_data .= " $data/*.*";
707
- else
708
- $include_data .= " '$data/*'";
709
- }
710
 
711
- //Additional includes?
712
- if (!empty($include)) {
713
- foreach ($include as $data) {
714
- if ($data) {
715
- if ($sys == 'WIN')
716
- $include_data .= " $data/*.*";
717
- else
718
- $include_data .= " '$data/*'";
719
- }
720
- }
721
- }
722
 
723
- $this->update_status($task_name, $this->statuses['files_zip']);
724
- chdir(ABSPATH);
725
- ob_start();
726
- $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
727
- $result_f = $this->mmb_exec($command, false, true);
728
- if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
729
- $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
730
- $result_d = $this->mmb_exec($command, false, true);
731
- if ($result_d && $result_d != 18) {
732
- @unlink($backup_file);
733
- if ($result_d > 0 && $result_d < 18)
734
- return array(
735
- 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
736
- );
737
- else
738
- return array(
739
- 'error' => 'Failed to archive files.'
740
- );
741
- }
742
  }
743
- ob_get_clean();
744
 
745
- if ($result_f && $result_f != 18) { //Try pclZip
746
- $this->_log("Files zip fallback to pclZip");
747
- if (!isset($archive)) {
748
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
749
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
750
- $archive = new PclZip($backup_file);
751
- }
752
-
753
- //Include paths
754
- $include_data = array();
755
- if (!empty($include)) {
756
- foreach ($include as $data) {
757
- if ($data && file_exists(ABSPATH . $data))
758
- $include_data[] = ABSPATH . $data . '/';
759
- }
760
- }
761
-
762
- foreach ($add as $data) {
763
- if (file_exists(ABSPATH . $data))
764
- $include_data[] = ABSPATH . $data . '/';
765
- }
766
-
767
- //Include root files
768
- if ($handle = opendir(ABSPATH)) {
769
- while (false !== ($file = readdir($handle))) {
770
- if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
771
- $include_data[] = ABSPATH . $file;
772
- }
773
- }
774
- closedir($handle);
775
- }
776
-
777
- if ($disable_comp) {
778
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION);
779
- } else {
780
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH);
781
- }
782
- if (!$result) {
783
- @unlink($backup_file);
784
- return array(
785
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
786
- );
787
- }
788
-
789
- //Now exclude paths
790
- $exclude_data = array();
791
- if (!empty($exclude)) {
792
- foreach ($exclude as $data) {
793
- if (is_dir(ABSPATH . $data))
794
- $exclude_data[] = $data . '/';
795
- else
796
- $exclude_data[] = $data;
797
- }
798
- }
799
-
800
- foreach ($remove as $rem) {
801
- $exclude_data[] = $rem . '/';
802
- }
803
-
804
- $result_excl = $archive->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
805
- if (!$result_excl) {
806
- @unlink($backup_file);
807
- return array(
808
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
809
- );
810
- }
811
-
812
  }
813
 
814
  //Reconnect
@@ -818,9 +644,379 @@ class MMB_Backup extends MMB_Core
818
  return true;
819
  }
820
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
821
 
822
- function backup_db()
823
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
  $db_folder = MWP_DB_DIR . '/';
825
  if (!file_exists($db_folder)) {
826
  if (!mkdir($db_folder, 0755, true))
@@ -834,8 +1030,13 @@ class MMB_Backup extends MMB_Core
834
  return $result;
835
  }
836
 
837
- function backup_db_dump($file)
838
- {
 
 
 
 
 
839
  global $wpdb;
840
  $paths = $this->check_mysql_paths();
841
  $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
@@ -858,8 +1059,13 @@ class MMB_Backup extends MMB_Core
858
  }
859
  }
860
 
861
- function backup_db_php($file)
862
- {
 
 
 
 
 
863
  global $wpdb;
864
  $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
865
  foreach ($tables as $table) {
@@ -874,7 +1080,7 @@ class MMB_Backup extends MMB_Core
874
  $count = ceil($count / 100);
875
  else if ($count > 0)
876
  $count = 1;
877
-
878
  for ($i = 0; $i < $count; $i++) {
879
  $low_limit = $i * 100;
880
  $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
@@ -911,9 +1117,17 @@ class MMB_Backup extends MMB_Core
911
  }
912
 
913
  return $file;
914
-
915
  }
916
 
 
 
 
 
 
 
 
 
 
917
  function restore($args) {
918
  global $wpdb;
919
  if (empty($args)) {
@@ -925,7 +1139,7 @@ class MMB_Backup extends MMB_Core
925
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
926
  }
927
  $this->set_memory();
928
-
929
  $unlink_file = true; //Delete file after restore
930
 
931
  //Detect source
@@ -950,6 +1164,7 @@ class MMB_Backup extends MMB_Core
950
  $args = $task['task_args']['account_info']['mwp_ftp'];
951
  $args['backup_file'] = $ftp_file;
952
  $backup_file = $this->get_ftp_backup($args);
 
953
  if ($backup_file == false) {
954
  return array(
955
  'error' => 'Failed to download file from FTP.'
@@ -960,6 +1175,7 @@ class MMB_Backup extends MMB_Core
960
  $args = $task['task_args']['account_info']['mwp_amazon_s3'];
961
  $args['backup_file'] = $amazons3_file;
962
  $backup_file = $this->get_amazons3_backup($args);
 
963
  if ($backup_file == false) {
964
  return array(
965
  'error' => 'Failed to download file from Amazon S3.'
@@ -993,7 +1209,6 @@ class MMB_Backup extends MMB_Core
993
  }
994
  }
995
 
996
-
997
  $what = $tasks[$task_name]['task_args']['what'];
998
  }
999
 
@@ -1017,28 +1232,23 @@ class MMB_Backup extends MMB_Core
1017
 
1018
  $clone_options = array();
1019
  if (trim($clone_from_url) || trim($mwp_clone)) {
1020
-
1021
  $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
1022
  $clone_options['_worker_public_key'] = get_option('_worker_public_key');
1023
  $clone_options['_action_message_id'] = get_option('_action_message_id');
1024
-
1025
  }
1026
- $clone_options['upload_path'] = get_option('upload_path');
1027
- $clone_options['upload_url_path'] = get_option('upload_url_path');
1028
-
1029
- $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
1030
- $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
1031
- $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
1032
-
1033
 
 
 
 
1034
  } else {
1035
  $restore_options = array();
1036
- $restore_options['mwp_notifications'] = get_option('mwp_notifications');
1037
- $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
1038
- $restore_options['user_hit_count'] = get_option('user_hit_count');
1039
  }
1040
 
1041
-
1042
  chdir(ABSPATH);
1043
  $unzip = $this->get_unzip();
1044
  $command = "$unzip -o $backup_file";
@@ -1066,7 +1276,7 @@ class MMB_Backup extends MMB_Core
1066
 
1067
  $db_result = $this->restore_db();
1068
 
1069
- if (!$db_result) {
1070
  return array(
1071
  'error' => 'Error restoring database.'
1072
  );
@@ -1169,24 +1379,24 @@ class MMB_Backup extends MMB_Core
1169
  //Check for .htaccess permalinks update
1170
  $this->replace_htaccess($home);
1171
  } else {
1172
-
1173
- //restore worker options
1174
- if (is_array($restore_options) && !empty($restore_options)) {
1175
  foreach ($restore_options as $key => $option) {
1176
  update_option($key,$option);
1177
  }
1178
- }
1179
-
1180
  }
1181
 
1182
-
1183
-
1184
-
1185
  return true;
1186
  }
1187
 
1188
- function restore_db()
1189
- {
 
 
 
 
 
1190
  global $wpdb;
1191
  $paths = $this->check_mysql_paths();
1192
  $file_path = ABSPATH . 'mwp_db';
@@ -1210,13 +1420,17 @@ class MMB_Backup extends MMB_Core
1210
  $this->restore_db_php($file_name);
1211
  }
1212
 
1213
-
1214
  @unlink($file_name);
1215
  return true;
1216
  }
1217
 
1218
- function restore_db_php($file_name)
1219
- {
 
 
 
 
 
1220
  global $wpdb;
1221
  $current_query = '';
1222
  // Read in entire file
@@ -1244,8 +1458,13 @@ class MMB_Backup extends MMB_Core
1244
  return true;
1245
  }
1246
 
1247
- function get_table_prefix()
1248
- {
 
 
 
 
 
1249
  $lines = file(ABSPATH . 'wp-config.php');
1250
  foreach ($lines as $line) {
1251
  if (strstr($line, '$table_prefix')) {
@@ -1259,8 +1478,12 @@ class MMB_Backup extends MMB_Core
1259
  return 'wp_'; //default
1260
  }
1261
 
1262
- function optimize_tables()
1263
- {
 
 
 
 
1264
  global $wpdb;
1265
  $query = 'SHOW TABLES';
1266
  $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
@@ -1284,9 +1507,12 @@ class MMB_Backup extends MMB_Core
1284
  return $optimize ? true : false;
1285
  }
1286
 
1287
- ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1288
- function check_mysql_paths()
1289
- {
 
 
 
1290
  global $wpdb;
1291
  $paths = array(
1292
  'mysql' => '',
@@ -1309,17 +1535,18 @@ class MMB_Backup extends MMB_Core
1309
 
1310
  $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1311
  if (empty($paths['mysqldump']))
1312
- $paths['mysqldump'] = 'mysqldump'; // try anyway
1313
-
1314
  }
1315
 
1316
-
1317
  return $paths;
1318
  }
1319
 
1320
- //Check if exec, system, passthru functions exist
1321
- function check_sys()
1322
- {
 
 
 
1323
  if ($this->mmb_function_exists('exec'))
1324
  return 'exec';
1325
 
@@ -1330,11 +1557,17 @@ class MMB_Backup extends MMB_Core
1330
  return 'passthru';
1331
 
1332
  return false;
1333
-
1334
  }
1335
 
1336
- function mmb_exec($command, $string = false, $rawreturn = false)
1337
- {
 
 
 
 
 
 
 
1338
  if ($command == '')
1339
  return false;
1340
 
@@ -1374,30 +1607,41 @@ class MMB_Backup extends MMB_Core
1374
 
1375
  if ($rawreturn)
1376
  return -1;
1377
-
1378
  return false;
1379
  }
1380
 
1381
- function get_zip()
1382
- {
 
 
 
 
1383
  $zip = $this->mmb_exec('which zip', true);
1384
  if (!$zip)
1385
  $zip = "zip";
1386
  return $zip;
1387
  }
1388
 
1389
- function get_unzip()
1390
- {
 
 
 
 
1391
  $unzip = $this->mmb_exec('which unzip', true);
1392
  if (!$unzip)
1393
  $unzip = "unzip";
1394
  return $unzip;
1395
  }
1396
 
1397
- function check_backup_compat()
1398
- {
1399
-
1400
- $reqs = array();
 
 
 
1401
  if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1402
  $reqs['Server OS']['status'] = 'Linux (or compatible)';
1403
  $reqs['Server OS']['pass'] = true;
@@ -1414,7 +1658,6 @@ class MMB_Backup extends MMB_Core
1414
  $pass = false;
1415
  }
1416
 
1417
-
1418
  if (is_writable(WP_CONTENT_DIR)) {
1419
  $reqs['Backup Folder']['status'] = "writable";
1420
  $reqs['Backup Folder']['pass'] = true;
@@ -1423,7 +1666,6 @@ class MMB_Backup extends MMB_Core
1423
  $reqs['Backup Folder']['pass'] = false;
1424
  }
1425
 
1426
-
1427
  $file_path = MWP_BACKUP_DIR;
1428
  $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1429
 
@@ -1435,14 +1677,10 @@ class MMB_Backup extends MMB_Core
1435
  $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1436
  $reqs['Execute Function']['pass'] = false;
1437
  }
1438
- $reqs['Zip']['status'] = $this->get_zip();
1439
 
 
1440
  $reqs['Zip']['pass'] = true;
1441
-
1442
-
1443
-
1444
  $reqs['Unzip']['status'] = $this->get_unzip();
1445
-
1446
  $reqs['Unzip']['pass'] = true;
1447
 
1448
  $paths = $this->check_mysql_paths();
@@ -1489,8 +1727,17 @@ class MMB_Backup extends MMB_Core
1489
  return $reqs;
1490
  }
1491
 
1492
- function email_backup($args)
1493
- {
 
 
 
 
 
 
 
 
 
1494
  $email = $args['email'];
1495
 
1496
  if (!is_email($email)) {
@@ -1518,13 +1765,23 @@ class MMB_Backup extends MMB_Core
1518
  );
1519
  }
1520
  return true;
1521
-
1522
  }
1523
 
1524
- function ftp_backup($args)
1525
- {
 
 
 
 
 
 
 
 
 
 
 
1526
  extract($args);
1527
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1528
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1529
  if ($ftp_ssl) {
1530
  if (function_exists('ftp_ssl_connect')) {
@@ -1560,15 +1817,15 @@ class MMB_Backup extends MMB_Core
1560
  }
1561
 
1562
  if($ftp_passive){
1563
- @ftp_pasv($conn_id,true);
1564
- }
1565
-
1566
  @ftp_mkdir($conn_id, $ftp_remote_folder);
1567
  if ($ftp_site_folder) {
1568
  $ftp_remote_folder .= '/' . $this->site_name;
1569
  }
1570
  @ftp_mkdir($conn_id, $ftp_remote_folder);
1571
-
1572
  $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1573
  if ($upload === false) { //Try ascii
1574
  $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
@@ -1585,10 +1842,21 @@ class MMB_Backup extends MMB_Core
1585
  return true;
1586
  }
1587
 
1588
- function remove_ftp_backup($args)
1589
- {
 
 
 
 
 
 
 
 
 
 
 
1590
  extract($args);
1591
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1592
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1593
  if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1594
  $conn_id = ftp_ssl_connect($ftp_hostname,$port);
@@ -1602,24 +1870,34 @@ class MMB_Backup extends MMB_Core
1602
  $ftp_remote_folder .= '/' . $this->site_name;
1603
 
1604
  if($ftp_passive){
1605
- @ftp_pasv($conn_id,true);
1606
- }
1607
-
1608
  $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1609
 
1610
  ftp_close($conn_id);
1611
  }
1612
-
1613
  }
1614
 
1615
- function get_ftp_backup($args)
1616
- {
 
 
 
 
 
 
 
 
 
 
 
1617
  extract($args);
1618
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1619
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1620
  if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1621
  $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1622
-
1623
  } else if (function_exists('ftp_connect')) {
1624
  $conn_id = ftp_connect($ftp_hostname,$port);
1625
  if ($conn_id === false) {
@@ -1629,157 +1907,164 @@ class MMB_Backup extends MMB_Core
1629
  $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1630
  if ($login === false) {
1631
  return false;
1632
- } else {
1633
  }
1634
 
1635
  if ($ftp_site_folder)
1636
  $ftp_remote_folder .= '/' . $this->site_name;
1637
 
1638
  if($ftp_passive){
1639
- @ftp_pasv($conn_id,true);
1640
- }
1641
 
1642
  $temp = ABSPATH . 'mwp_temp_backup.zip';
1643
  $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1644
  if ($get === false) {
1645
  return false;
1646
- } else {
1647
  }
 
1648
  ftp_close($conn_id);
1649
 
1650
  return $temp;
1651
  }
1652
 
1653
- function dropbox_backup($args)
1654
- {
1655
-
 
 
 
 
 
 
 
 
 
 
 
1656
  extract($args);
1657
 
1658
- if(isset($consumer_secret) && !empty($consumer_secret)){
1659
- //New way
1660
- require_once('lib/dropbox.oauth.php');
1661
-
1662
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1663
- $dropbox->setOAuthToken($oauth_token);
1664
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1665
-
1666
- if ($dropbox_site_folder == true)
1667
- $dropbox_destination .= '/' . $this->site_name;
1668
-
1669
- try{
1670
-
1671
- $dropbox->filesPost($dropbox_destination, $backup_file,true);
1672
-
1673
- } catch(Exception $e){
1674
- return array(
1675
- 'error' => 'Dropbox upload error. '.$e->getMessage()
1676
- );
1677
- }
1678
-
1679
- return true;
1680
-
1681
- } else {
1682
- //old way
1683
- require_once('lib/dropbox.php');
1684
-
1685
- //$email, $password, $backup_file, $destination, $dropbox_site_folder
1686
 
1687
- $size = ceil(filesize($backup_file) / 1024);
1688
- if ($size > 300000) {
1689
- return array(
1690
- 'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
1691
- 'partial' => 1
1692
- );
1693
- }
1694
 
1695
  if ($dropbox_site_folder == true)
1696
- $dropbox_destination .= '/' . $this->site_name;
 
 
1697
 
1698
  try {
1699
- $uploader = new DropboxUploader($dropbox_username, $dropbox_password);
1700
- $uploader->upload($backup_file, $dropbox_destination);
1701
- }
1702
- catch (Exception $e) {
1703
- return array(
1704
- 'error' => $e->getMessage(),
1705
- 'partial' => 1
1706
- );
1707
  }
1708
 
1709
  return true;
1710
- }
1711
-
1712
- }
1713
-
1714
- function remove_dropbox_backup($args){
1715
- extract($args);
1716
- if(isset($consumer_secret) && !empty($consumer_secret)){
1717
- //New way
1718
- require_once('lib/dropbox.oauth.php');
1719
-
1720
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1721
- $dropbox->setOAuthToken($oauth_token);
1722
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1723
-
1724
- if ($dropbox_site_folder == true)
1725
- $dropbox_destination .= '/' . $this->site_name;
1726
-
1727
- try{
1728
- $dropbox->fileopsDelete($dropbox_destination.'/'.$backup_file, true);
1729
- } catch(Exception $e){
1730
-
1731
- }
1732
- }
1733
- }
1734
-
1735
- function get_dropbox_backup($args){
1736
- extract($args);
1737
-
1738
- if(isset($consumer_secret) && !empty($consumer_secret)){
1739
- //New way
1740
- require_once('lib/dropbox.oauth.php');
1741
-
1742
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1743
- $dropbox->setOAuthToken($oauth_token);
1744
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1745
-
1746
- if ($dropbox_site_folder == true)
1747
- $dropbox_destination .= '/' . $this->site_name;
1748
-
1749
- $temp = ABSPATH . 'mwp_temp_backup.zip';
1750
-
1751
- try{
1752
- $file = $dropbox->filesGet($dropbox_destination.'/'.$backup_file, true);
1753
-
1754
- if(isset($file['data']) && !empty($file['data']) )
1755
- $stream = base64_decode($file['data']);
1756
- else
1757
- return false;
1758
-
1759
- $handle = @fopen($temp, 'w+');
1760
- $result = fwrite($handle,$stream);
1761
- fclose($handle);
1762
-
1763
- if($result)
1764
- return $temp;
1765
- else
1766
- return false;
1767
-
1768
- } catch(Exception $e){
1769
-
1770
-
1771
- return false;
1772
- }
1773
-
1774
- } else {
1775
- return false;
1776
  }
1777
 
1778
-
1779
- }
1780
-
1781
- function amazons3_backup($args)
1782
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1783
  if ($this->mmb_function_exists('curl_init')) {
1784
  require_once('lib/s3.php');
1785
  extract($args);
@@ -1789,29 +2074,28 @@ class MMB_Backup extends MMB_Core
1789
 
1790
  $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1791
  try{
1792
- $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1793
- if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
1794
- return true;
1795
- } else {
1796
-
1797
- return array(
1798
- 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
1799
- 'partial' => 1
1800
- );
1801
- }
1802
-
1803
- }catch (Exception $e){
1804
- $err = $e->getMessage();
1805
- if($err){
1806
- return array(
1807
- 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
1808
- );
1809
- } else {
1810
- return array(
1811
- 'error' => 'Failed to upload to Amazon S3.'
1812
- );
1813
- }
1814
- }
1815
 
1816
  } else {
1817
  return array(
@@ -1821,49 +2105,75 @@ class MMB_Backup extends MMB_Core
1821
  }
1822
  }
1823
 
1824
- function remove_amazons3_backup($args)
1825
- {
 
 
 
 
 
 
 
 
 
 
 
 
1826
  if ($this->mmb_function_exists('curl_init')) {
1827
- require_once('lib/s3.php');
1828
- extract($args);
1829
- if ($as3_site_folder == true)
1830
- $as3_directory .= '/' . $this->site_name;
1831
- $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1832
- try{
1833
- $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1834
- $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
1835
- } catch (Exception $e){
1836
-
1837
- }
1838
- }
1839
  }
1840
 
1841
- function get_amazons3_backup($args)
1842
- {
 
 
 
 
 
 
 
 
 
 
 
 
1843
  require_once('lib/s3.php');
1844
  extract($args);
1845
  $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1846
  $temp = '';
1847
- try{
1848
- $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1849
- if ($as3_site_folder == true)
1850
- $as3_directory .= '/' . $this->site_name;
1851
-
1852
- $temp = ABSPATH . 'mwp_temp_backup.zip';
1853
- $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
1854
- } catch (Exception $e){
1855
- return $temp;
1856
- }
1857
- return $temp;
1858
  }
1859
 
1860
- /*
1861
- * Uploads current backup file to Google Drive
1862
- *
1863
- * @param array @args arguments passed to function
1864
- * @arg array google_drive_token tokens passed from master
1865
- * @arg string google_drive_directory drive default directory for backups
1866
- * @arg string google_drive_site_folder
 
 
1867
  */
1868
  function google_drive_backup($args) {
1869
  extract($args);
@@ -1904,7 +2214,7 @@ class MMB_Backup extends MMB_Core
1904
  $_managewp_folder = new Google_DriveFile();
1905
  $_managewp_folder->setTitle($google_drive_directory);
1906
  $_managewp_folder->setMimeType('application/vnd.google-apps.folder');
1907
-
1908
  if ($root_folder_id != null) {
1909
  $parent = new Google_ParentReference();
1910
  $parent->setId($root_folder_id);
@@ -1961,22 +2271,43 @@ class MMB_Backup extends MMB_Core
1961
  if ($backup_folder != null) {
1962
  $new_file->setParents(array($backup_folder));
1963
  }
1964
-
1965
- try {
1966
- $data = file_get_contents($backup_file);
1967
-
1968
- $createdFile = $gdrive_service->files->insert($new_file, array(
1969
- 'data' => $data,
1970
- ));
1971
- } catch (Exception $e) {
1972
- return array(
1973
- 'error' => $e->getMessage(),
1974
- );
 
 
 
 
 
 
 
 
 
 
 
1975
  }
1976
 
1977
  return true;
1978
  }
1979
 
 
 
 
 
 
 
 
 
 
 
1980
  function remove_google_drive_backup($args) {
1981
  extract($args);
1982
 
@@ -1990,11 +2321,11 @@ class MMB_Backup extends MMB_Core
1990
  $gdrive_client->setAccessToken($google_drive_token);
1991
  } catch (Exception $e) {
1992
  $this->_log($e->getMessage());
1993
- return array(
1994
  'error' => $e->getMessage(),
1995
- );
1996
  }
1997
-
1998
  $gdrive_service = new Google_DriveService($gdrive_client);
1999
 
2000
  try {
@@ -2002,9 +2333,9 @@ class MMB_Backup extends MMB_Core
2002
  $root_folder_id = $about->getRootFolderId();
2003
  } catch (Exception $e) {
2004
  $this->_log($e->getMessage());
2005
- return array(
2006
  'error' => $e->getMessage(),
2007
- );
2008
  }
2009
 
2010
  try {
@@ -2012,17 +2343,17 @@ class MMB_Backup extends MMB_Core
2012
  $files = $list_files->getItems();
2013
  } catch (Exception $e) {
2014
  $this->_log($e->getMessage());
2015
- return array(
2016
  'error' => $e->getMessage(),
2017
- );
2018
  }
2019
  if (isset($files[0])) {
2020
  $managewp_folder = $files[0];
2021
  } else {
2022
  $this->_log("This file does not exist.");
2023
- return array(
2024
  'error' => "This file does not exist.",
2025
- );
2026
  }
2027
 
2028
  if ($google_drive_site_folder) {
@@ -2033,9 +2364,9 @@ class MMB_Backup extends MMB_Core
2033
  $files = $list_files->getItems();
2034
  } catch (Exception $e) {
2035
  $this->_log($e->getMessage());
2036
- return array(
2037
  'error' => $e->getMessage(),
2038
- );
2039
  }
2040
  if (isset($files[0])) {
2041
  $backup_folder = $files[0];
@@ -2051,35 +2382,45 @@ class MMB_Backup extends MMB_Core
2051
  $files = $list_files->getItems();;
2052
  } catch (Exception $e) {
2053
  $this->_log($e->getMessage());
2054
- return array(
2055
  'error' => $e->getMessage(),
2056
- );
2057
  }
2058
  if (isset($files[0])) {
2059
  try {
2060
  $gdrive_service->files->delete($files[0]->getId());
2061
  } catch (Exception $e) {
2062
  $this->_log($e->getMessage());
2063
- return array(
2064
  'error' => $e->getMessage(),
2065
- );
2066
  }
2067
  } else {
2068
  $this->_log("This file does not exist.");
2069
- return array(
2070
  'error' => "This file does not exist.",
2071
- );
2072
  }
2073
  } else {
2074
  $this->_log("This file does not exist.");
2075
- return array(
2076
  'error' => "This file does not exist.",
2077
- );
2078
  }
2079
 
2080
- return true;
2081
  }
2082
 
 
 
 
 
 
 
 
 
 
 
2083
  function get_google_drive_backup($args) {
2084
  extract($args);
2085
 
@@ -2141,7 +2482,7 @@ class MMB_Backup extends MMB_Core
2141
  } else {
2142
  $backup_folder = $managewp_folder;
2143
  }
2144
-
2145
  if (isset($backup_folder)) {
2146
  try {
2147
  $backup_folder_id = $backup_folder->getId();
@@ -2199,16 +2540,20 @@ class MMB_Backup extends MMB_Core
2199
  return false;
2200
  }
2201
 
2202
- function schedule_next($type, $schedule)
2203
- {
 
 
 
 
 
 
2204
  $schedule = explode("|", $schedule);
2205
 
2206
  if (empty($schedule))
2207
  return false;
2208
  switch ($type) {
2209
-
2210
  case 'daily':
2211
-
2212
  if (isset($schedule[1]) && $schedule[1]) {
2213
  $delay_time = $schedule[1] * 60;
2214
  }
@@ -2221,7 +2566,6 @@ class MMB_Backup extends MMB_Core
2221
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2222
  break;
2223
 
2224
-
2225
  case 'weekly':
2226
  if (isset($schedule[2]) && $schedule[2]) {
2227
  $delay_time = $schedule[2] * 60;
@@ -2236,7 +2580,6 @@ class MMB_Backup extends MMB_Core
2236
  else
2237
  $weekday_offset = $schedule_weekday - $current_weekday;
2238
 
2239
-
2240
  if (!$weekday_offset) { //today is scheduled weekday
2241
  if ($current_hour >= $schedule_hour)
2242
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
@@ -2245,9 +2588,8 @@ class MMB_Backup extends MMB_Core
2245
  } else {
2246
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
2247
  }
2248
-
2249
  break;
2250
-
2251
  case 'monthly':
2252
  if (isset($schedule[2]) && $schedule[2]) {
2253
  $delay_time = $schedule[2] * 60;
@@ -2270,6 +2612,7 @@ class MMB_Backup extends MMB_Core
2270
  }
2271
 
2272
  break;
 
2273
  default:
2274
  break;
2275
  }
@@ -2279,12 +2622,14 @@ class MMB_Backup extends MMB_Core
2279
  }
2280
 
2281
  return $time;
2282
-
2283
  }
2284
 
2285
- //Parse task arguments for info on master
2286
- function get_backup_stats()
2287
- {
 
 
 
2288
  $stats = array();
2289
  $tasks = $this->tasks;
2290
  if (is_array($tasks) && !empty($tasks)) {
@@ -2292,22 +2637,27 @@ class MMB_Backup extends MMB_Core
2292
  if (is_array($info['task_results']) && !empty($info['task_results'])) {
2293
  foreach ($info['task_results'] as $key => $result) {
2294
  if (isset($result['server']) && !isset($result['error'])) {
2295
- if (!file_exists($result['server']['file_path'])) {
2296
- $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
 
 
2297
  }
2298
  }
2299
  }
2300
  }
2301
  if (is_array($info['task_results']))
2302
  $stats[$task_name] = array_values($info['task_results']);
2303
-
2304
  }
2305
  }
2306
  return $stats;
2307
  }
2308
 
2309
- function get_next_schedules()
2310
- {
 
 
 
 
2311
  $stats = array();
2312
  $tasks = $this->tasks;
2313
  if (is_array($tasks) && !empty($tasks)) {
@@ -2318,9 +2668,14 @@ class MMB_Backup extends MMB_Core
2318
  return $stats;
2319
  }
2320
 
2321
- function remove_old_backups($task_name)
2322
- {
2323
-
 
 
 
 
 
2324
  //Check for previous failed backups first
2325
  $this->cleanup();
2326
 
@@ -2332,7 +2687,6 @@ class MMB_Backup extends MMB_Core
2332
  $num = 1;
2333
  }
2334
 
2335
-
2336
  if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
2337
  //how many to remove ?
2338
  $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
@@ -2362,7 +2716,7 @@ class MMB_Backup extends MMB_Core
2362
  $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
2363
  $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
2364
  $args['backup_file'] = $dropbox_file;
2365
- $this->remove_dropbox_backup($args);
2366
  }
2367
 
2368
  if (isset($backups[$task_name]['task_results'][$i]['google_drive']) && isset($backups[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
@@ -2372,7 +2726,6 @@ class MMB_Backup extends MMB_Core
2372
  $this->remove_google_drive_backup($args);
2373
  }
2374
 
2375
-
2376
  //Remove database backup info
2377
  unset($backups[$task_name]['task_results'][$i]);
2378
  } //end foreach
@@ -2381,19 +2734,22 @@ class MMB_Backup extends MMB_Core
2381
  $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
2382
  else
2383
  $backups[$task_name]['task_results']=array();
2384
-
2385
  $this->update_tasks($backups);
2386
- //update_option('mwp_backup_tasks', $backups);
2387
 
2388
  return true;
2389
  }
2390
  }
2391
 
2392
  /**
2393
- * Delete specified backup
2394
- * Args: $task_name, $result_id
 
 
 
 
 
2395
  */
2396
-
2397
  function delete_backup($args) {
2398
  if (empty($args))
2399
  return false;
@@ -2440,7 +2796,6 @@ class MMB_Backup extends MMB_Core
2440
  $this->remove_google_drive_backup($args);
2441
  }
2442
 
2443
-
2444
  unset($backups[$result_id]);
2445
 
2446
  if (count($backups)) {
@@ -2452,11 +2807,14 @@ class MMB_Backup extends MMB_Core
2452
  $this->update_tasks($tasks);
2453
  //update_option('mwp_backup_tasks', $tasks);
2454
  return true;
2455
-
2456
  }
2457
 
2458
- function cleanup()
2459
- {
 
 
 
 
2460
  $tasks = $this->tasks;
2461
  $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
2462
  $backup_folder_new = MWP_BACKUP_DIR . '/';
@@ -2474,7 +2832,6 @@ class MMB_Backup extends MMB_Core
2474
  @rmdir(MWP_DB_DIR);
2475
  }
2476
 
2477
-
2478
  //clean_old folder?
2479
  if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
2480
  foreach ($files as $file) {
@@ -2484,7 +2841,6 @@ class MMB_Backup extends MMB_Core
2484
  @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
2485
  }
2486
 
2487
-
2488
  foreach ($new as $b) {
2489
  $files[] = $b;
2490
  }
@@ -2514,24 +2870,28 @@ class MMB_Backup extends MMB_Core
2514
  }
2515
  }
2516
 
2517
-
2518
-
2519
  return $deleted;
2520
  }
2521
 
2522
-
 
 
 
 
 
 
2523
  function remote_backup_now($args) {
2524
  $this->set_memory();
2525
  if (!empty($args))
2526
  extract($args);
2527
 
2528
  $tasks = $this->tasks;
2529
- $task = $tasks['Backup Now'];
2530
 
2531
  if (!empty($task)) {
2532
  extract($task['task_args']);
2533
  }
2534
-
2535
  $results = $task['task_results'];
2536
 
2537
  if (is_array($results) && count($results)) {
@@ -2541,42 +2901,62 @@ class MMB_Backup extends MMB_Core
2541
  if ($backup_file && file_exists($backup_file)) {
2542
  //FTP, Amazon S3, Dropbox or Google Drive
2543
  if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
2544
- $account_info['mwp_ftp']['backup_file'] = $backup_file;
 
2545
  $return = $this->ftp_backup($account_info['mwp_ftp']);
 
 
 
 
2546
  }
2547
 
2548
  if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
2549
- $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
 
2550
  $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
 
 
 
 
2551
  }
2552
 
2553
  if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
2554
- $account_info['mwp_dropbox']['backup_file'] = $backup_file;
 
2555
  $return = $this->dropbox_backup($account_info['mwp_dropbox']);
 
 
 
 
2556
  }
2557
 
2558
  if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
2559
- $account_info['mwp_email']['file_path'] = $backup_file;
2560
- $account_info['mwp_email']['task_name'] = 'Backup Now';
2561
  $return = $this->email_backup($account_info['mwp_email']);
 
 
 
 
2562
  }
2563
 
2564
  if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
 
2565
  $account_info['mwp_google_drive']['backup_file'] = $backup_file;
2566
  $return = $this->google_drive_backup($account_info['mwp_google_drive']);
 
 
 
 
2567
  }
2568
 
2569
-
2570
  @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
2571
  if ($return == true && $del_host_file) {
2572
  @unlink($backup_file);
2573
- unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
2574
- $this->update_tasks($tasks);
2575
- //update_option('mwp_backup_tasks', $tasks);
2576
  }
2577
-
2578
-
2579
-
2580
  } else {
2581
  $return = array(
2582
  'error' => 'Backup file not found on your server. Please try again.'
@@ -2584,62 +2964,83 @@ class MMB_Backup extends MMB_Core
2584
  }
2585
 
2586
  return $return;
2587
-
2588
  }
2589
 
2590
- function validate_task($args, $url)
2591
- {
 
 
 
 
 
 
 
 
 
 
 
2592
  if (!class_exists('WP_Http')) {
2593
  include_once(ABSPATH . WPINC . '/class-http.php');
2594
  }
 
 
2595
  $params = array('timeout'=>100);
2596
  $params['body'] = $args;
2597
  $result = wp_remote_post($url, $params);
2598
- if (is_array($result) && $result['body'] == 'mwp_delete_task') {
2599
- //$tasks = $this->get_backup_settings();
2600
- $tasks = $this->tasks;
2601
- unset($tasks[$args['task_name']]);
2602
- $this->update_tasks($tasks);
2603
- $this->cleanup();
2604
- exit;
2605
- } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
2606
- return 'paused';
2607
- } elseif(is_array($result) && substr($result['body'], 0, 8) == 'token - '){
2608
- return $result['body'];
2609
- }
2610
 
2611
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2612
  }
2613
 
2614
- /*function refresh_gdrive_token($args, $url)
2615
- {
2616
- if (!class_exists('WP_Http')) {
2617
- include_once(ABSPATH . WPINC . '/class-http.php');
2618
- }
2619
- $params = array('timeout'=>100);
2620
- $params['body'] = $args;
2621
- $result = wp_remote_post($url, $params);
2622
- if(isset($result['body'])) {
2623
- return $result['body'];
2624
- }
2625
-
2626
- return false;
2627
- }*/
2628
-
2629
- function update_status($task_name, $status, $completed = false)
2630
- {
2631
- /* Statuses:
2632
- 0 - Backup started
2633
- 1 - DB dump
2634
- 2 - DB ZIP
2635
- 3 - Files ZIP
2636
- 4 - Amazon S3
2637
- 5 - Dropbox
2638
- 6 - FTP
2639
- 7 - Email
2640
- 8 - Google Drive
2641
- 100 - Finished
2642
- */
2643
  if ($task_name != 'Backup Now') {
2644
  $tasks = $this->tasks;
2645
  $index = count($tasks[$task_name]['task_results']) - 1;
@@ -2658,15 +3059,25 @@ class MMB_Backup extends MMB_Core
2658
  }
2659
  }
2660
 
2661
- function update_tasks($tasks)
2662
- {
 
 
 
 
 
2663
  $this->tasks = $tasks;
2664
  update_option('mwp_backup_tasks', $tasks);
2665
  }
2666
 
2667
- function wpdb_reconnect(){
 
 
 
 
 
2668
  global $wpdb;
2669
- //Reconnect to avoid timeout problem after ZIP files
2670
  if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
2671
  @mysql_close($wpdb->dbh);
2672
  $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
@@ -2674,27 +3085,43 @@ class MMB_Backup extends MMB_Core
2674
  }
2675
  }
2676
 
2677
- function replace_htaccess($url)
2678
- {
2679
- $file = @file_get_contents(ABSPATH.'.htaccess');
2680
- if ($file && strlen($file)) {
2681
- $args = parse_url($url);
2682
- $string = rtrim($args['path'], "/");
2683
- $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
2684
- $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
2685
- $file = preg_replace($regex, $replace, $file);
2686
- @file_put_contents(ABSPATH.'.htaccess', $file);
2687
- }
 
 
 
 
 
2688
  }
2689
 
2690
- function check_cron_remove(){
 
 
 
 
 
2691
  if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
2692
  wp_clear_scheduled_hook('mwp_backup_tasks');
2693
  exit;
2694
  }
2695
  }
2696
 
2697
- public static function readd_tasks( $params = array() ){
 
 
 
 
 
 
2698
  global $mmb_core;
2699
 
2700
  if( empty($params) || !isset($params['backups']) )
@@ -2741,9 +3168,153 @@ class MMB_Backup extends MMB_Core
2741
  unset($params['backups']);
2742
  return $params;
2743
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2744
  }
2745
 
2746
- if( function_exists('add_filter') ){
2747
  add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
2748
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2749
  ?>
16
  define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
17
  define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
18
 
19
+ $zip_errors = array(
20
  'No error',
21
  'No error',
22
  'Unexpected end of zip file',
57
  82 => 'No files were found due to bad decryption password(s)'
58
  );
59
 
60
+ /**
61
+ * The main class for processing database and full backups on ManageWP worker.
62
+ *
63
+ * @copyright 2011-2012 Prelovac Media
64
+ * @version 3.9.24
65
+ * @package ManageWP
66
+ * @subpackage backup
67
+ *
68
+ */
69
+ class MMB_Backup extends MMB_Core {
70
  var $site_name;
71
  var $statuses;
72
  var $tasks;
74
  var $ftp;
75
  var $dropbox;
76
  var $google_drive;
77
+
78
+ /**
79
+ * Initializes site_name, statuses, and tasks attributes.
80
+ *
81
+ * @return void
82
+ */
83
+ function __construct() {
84
  parent::__construct();
85
  $this->site_name = str_replace(array(
86
  "_",
105
  $this->tasks = get_option('mwp_backup_tasks');
106
  }
107
 
108
+ /**
109
+ * Tries to increase memory limit to 384M and execution time to 600s.
110
+ *
111
+ * @return array an array with two keys for execution time and memory limit (0 - if not changed, 1 - if succesfully)
112
+ */
113
+ function set_memory() {
114
  $changed = array('execution_time' => 0, 'memory_limit' => 0);
115
 
116
  $memory_limit = trim(ini_get('memory_limit'));
117
  $last = strtolower(substr($memory_limit, -1));
118
+
119
  if($last == 'g')
120
  $memory_limit = ((int) $memory_limit)*1024;
121
  else if($last == 'm')
124
  $memory_limit = ((int) $memory_limit)/1024;
125
 
126
  if ( $memory_limit < 384 ) {
127
+ @ini_set('memory_limit', '384M');
128
+ $changed['memory_limit'] = 1;
129
+ }
130
+
131
+ if ( (int) @ini_get('max_execution_time') < 600 ) {
132
+ @set_time_limit(600); //ten minutes
133
  $changed['execution_time'] = 1;
134
  }
135
 
136
  return $changed;
 
137
  }
138
 
139
+ /**
140
+ * Returns backup settings from local database for all tasks
141
+ *
142
+ * @return mixed|boolean
143
+ */
144
+ function get_backup_settings() {
145
  $backup_settings = get_option('mwp_backup_tasks');
146
 
147
  if (!empty($backup_settings))
150
  return false;
151
  }
152
 
153
+ /**
154
+ * Sets backup task defined from master, if task name is "Backup Now" this function fires processing backup.
155
+ *
156
+ * @param mixed $params parameters sent from master
157
+ * @return mixed|boolean $this->tasks variable if success, array with error message if error has ocurred, false if $params are empty
158
+ */
159
+ function set_backup_task($params) {
160
  //$params => [$task_name, $args, $error]
161
  if (!empty($params)) {
162
+
163
  //Make sure backup cron job is set
164
+ if (!wp_next_scheduled('mwp_backup_tasks')) {
165
+ wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
166
+ }
167
 
168
  extract($params);
169
+
170
  //$before = $this->get_backup_settings();
171
  $before = $this->tasks;
172
  if (!$before || empty($before))
209
  //update_option('mwp_backup_tasks', $before);
210
 
211
  if ($task_name == 'Backup Now') {
212
+ $result = $this->backup($args, $task_name);
213
  $backup_settings = $this->tasks;
214
 
215
  if (is_array($result) && array_key_exists('error', $result)) {
216
+ $return = $result;
217
  } else {
218
  $return = $backup_settings[$task_name];
219
  }
221
  return $return;
222
  }
223
 
 
 
224
  return false;
225
  }
226
 
227
+ /**
228
+ * Checks if scheduled task is ready for execution,
229
+ * if it is ready master sends google_drive_token, failed_emails, success_emails if are needed.
230
+ *
231
+ * @return void
232
+ */
233
  function check_backup_tasks() {
234
  $this->check_cron_remove();
235
 
236
+ $failed_emails = array();
237
  $settings = $this->tasks;
238
  if (is_array($settings) && !empty($settings)) {
239
  foreach ($settings as $task_name => $setting) {
244
  $check_data = array(
245
  'task_name' => $task_name,
246
  'task_id' => $setting['task_args']['task_id'],
247
+ 'site_key' => $setting['task_args']['site_key'],
248
+ 'worker_version' => MMB_WORKER_VERSION
249
  );
250
 
251
  if (isset($setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'])) {
253
  }
254
 
255
  $check = $this->validate_task($check_data, $setting['task_args']['url']);
256
+ $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
257
 
258
+ if ($worker_upto_3_9_22) {
259
+ $potential_token = substr($check, 8);
260
+ if (substr($check, 0, 8) == 'token - ' && $potential_token != 'not found') {
261
+ $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
262
+ $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
263
+ $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
264
+ }
265
+ } else {
266
+ $potential_token = isset($check['google_drive_token']) ? $check['google_drive_token'] : false;
267
+ if ($potential_token) {
268
+ $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
269
+ $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
270
+ $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
271
+ }
272
  }
273
 
274
  }
275
+
276
  $update = array(
277
  'task_name' => $task_name,
278
  'args' => $settings[$task_name]['task_args']
279
  );
280
 
 
281
  if($check != 'paused'){
282
  $update['time'] = time();
283
  }
300
  'error' => $error
301
  ));
302
  } else {
303
+ $setting = $this->tasks[$task_name];
304
+ if (@count($setting['task_args']['account_info'])) {
305
+ $last_result = $setting['task_results'][count($setting['task_results']) - 1];
306
+ $backup_file = $last_result['server']['file_path'];
307
+ $del_host_file = $setting['task_args']['del_host_file'];
308
+ wp_schedule_single_event(time(), 'mmb_scheduled_remote_upload', array('args' => array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)));
309
+ //spawn_cron(time() + 150);
310
+ //wp_remote_post(site_url('index.php'), array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ));
311
+ //update_option('_transient_doing_cron', 0);
312
+ /*$nonce = substr(wp_hash(wp_nonce_tick() . 'mmb-backup-nonce' . 0, 'nonce'), -12, 10);
313
+ $cron_url = site_url('index.php');
314
+ $args = array(
315
+ 'body' => array(
316
+ 'backup_cron_action' => 'mmb_remote_upload',
317
+ 'args' => json_encode(array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)),
318
+ 'mmb_backup_nonce' => $nonce,
319
+ ),
320
+ 'timeout' => 0.01,
321
+ 'blocking' => false,
322
+ 'sslverify' => apply_filters('https_local_ssl_verify', true)
323
+ );
324
+ wp_remote_post($cron_url, $args);*/
325
+ }
326
  }
327
 
328
  break; //Only one backup per cron
332
 
333
  }
334
 
335
+ /**
336
+ * Runs backup task invoked from ManageWP master.
337
+ *
338
+ * @param string $task_name name of backup task
339
+ * @param string|bool[optional] $google_drive_token false if backup destination is not Google Drive, json of Google Drive token if it is remote destination (default: false)
340
+ * @return mixed array with backup statistics if successful, array with error message if not
341
+ */
342
+ function task_now($task_name, $google_drive_token = false) {
343
  if ($google_drive_token) {
344
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
345
  }
350
  } else {
351
  $setting = $settings[$task_name];
352
  }
353
+
354
  $this->set_backup_task(array(
355
  'task_name' => $task_name,
356
  'args' => $settings[$task_name]['task_args'],
373
  }
374
  }
375
 
376
+ /**
377
+ * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
378
+ * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
379
+ *
380
+ * @param string $args arguments passed from master
381
+ * [type] -> db, full,
382
+ * [what] -> daily, weekly, monthly,
383
+ * [account_info] -> remote destinations ftp, amazons3, dropbox, google_drive, email with their parameters
384
+ * [include] -> array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
385
+ * [exclude] -> array of files of folders to exclude, relative to site's root
386
+ * @param bool|string[optional] $task_name the name of backup task, which backup is done (default: false)
387
+ * @return bool|array false if $args are missing, array with error if error has occured, ture if is successful
388
  */
 
389
  function backup($args, $task_name = false) {
390
  if (!$args || empty($args))
391
  return false;
392
 
393
  extract($args); //extract settings
394
 
395
+ if (!empty($account_info)) {
396
+ $found = false;
397
+ $destinations = array('mwp_ftp', 'mwp_amazon_s3', 'mwp_dropbox', 'mwp_google_drive', 'mwp_email');
398
+ foreach($destinations as $dest) {
399
+ $found = $found || (isset($account_info[$dest]));
400
+ }
401
+ if (!$found) {
402
+ $error_message = 'Remote destination is not supported, please update your client plugin.';
403
+ return array(
404
+ 'error' => $error_message
405
+ );
406
+ }
407
+ }
408
 
409
  //Try increase memory limit and execution time
410
  $this->set_memory();
412
  //Remove old backup(s)
413
  $removed = $this->remove_old_backups($task_name);
414
  if (is_array($removed) && isset($removed['error'])) {
415
+ $error_message = $removed['error'];
416
  return $removed;
417
  }
418
 
420
 
421
  if (!file_exists($new_file_path)) {
422
  if (!mkdir($new_file_path, 0755, true))
423
+ $error_message = 'Permission denied, make sure you have write permission to wp-content folder.';
424
+ return array(
425
+ 'error' => $error_message
426
+ );
427
  }
428
 
429
  @file_put_contents($new_file_path . '/index.php', ''); //safe
430
+
431
  //Prepare .zip file name
432
  $hash = md5(time());
433
  $label = $type ? $type : 'manual';
434
  $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
435
  $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
436
 
437
+ $begin_compress = microtime(true);
438
+
439
  //Optimize tables?
440
  if (isset($optimize_tables) && !empty($optimize_tables)) {
441
  $this->optimize_tables();
442
  }
443
+
444
  //What to backup - db or full?
445
  if (trim($what) == 'db') {
446
+ $db_backup = $this->backup_db_compress($task_name, $backup_file);
447
+ if (is_array($db_backup) && array_key_exists('error', $db_backup)) {
448
+ $error_message = $db_backup['error'];
449
+ return array(
450
+ 'error' => $error_message
451
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  }
453
  } elseif (trim($what) == 'full') {
454
+ if (!$exclude) {
455
+ $exclude = array();
456
+ }
457
+ if (!$include) {
458
+ $include = array();
459
+ }
460
+ $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
461
  if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
462
+ $error_message = $content_backup['error'];
463
+ return array(
464
+ 'error' => $error_message
465
  );
466
  }
467
  }
468
 
469
+ $end_compress = microtime(true);
470
+
471
  //Update backup info
472
  if ($task_name) {
473
  //backup task (scheduled)
474
  $backup_settings = $this->tasks;
475
  $paths = array();
476
  $size = ceil(filesize($backup_file) / 1024);
477
+ $duration = round($end_compress - $begin_compress, 2);
478
 
479
  if ($size > 1000) {
480
+ $paths['size'] = ceil($size / 1024) . "mb";
481
  } else {
482
  $paths['size'] = $size . 'kb';
483
  }
484
 
485
+ $paths['duration'] = $duration . 's';
486
+
487
  if ($task_name != 'Backup Now') {
488
+ $paths['server'] = array(
489
+ 'file_path' => $backup_file,
490
+ 'file_url' => $backup_url
491
+ );
 
 
492
  } else {
493
  $paths['server'] = array(
494
  'file_path' => $backup_file,
533
  //update_option('mwp_backup_tasks', $backup_settings);
534
  }
535
 
536
+ // If there are not remote destination, set up task status to finished
537
+ if (@count($backup_settings[$task_name]['task_args']['account_info']) == 0) {
538
+ $this->update_status($task_name,$this->statuses['finished'], true);
539
+ }
540
 
541
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  }
543
 
544
+ /**
545
+ * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
546
+ * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
547
+ *
548
+ * @param string $task_name the name of backup task, which backup is done
549
+ * @param string $backup_file relative path to file which backup is stored
550
+ * @param array[optional] $exclude the list of files and folders, which are excluded from backup (default: array())
551
+ * @param array[optional] $include the list of folders in wordpress root which are included to backup, expect wp-admin, wp-content, wp-includes, which are default (default: array())
552
+ * @return bool|array true if backup is successful, or an array with error message if is failed
553
+ */
554
+ function backup_full($task_name, $backup_file, $exclude = array(), $include = array()) {
555
+ $this->update_status($task_name, $this->statuses['db_dump']);
556
  $db_result = $this->backup_db();
557
 
558
  if ($db_result == false) {
566
  }
567
 
568
  $this->update_status($task_name, $this->statuses['db_dump'], true);
569
+ $this->update_status($task_name, $this->statuses['db_zip']);
 
 
 
 
 
 
 
 
 
 
 
570
 
571
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
572
+ $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
573
+
574
+ if (!$zip_db_result) {
575
+ $zip_archive_db_result = false;
576
+ if (class_exists("ZipArchive")) {
577
+ $this->_log("DB zip, fallback to ZipArchive");
578
+ $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
579
+ }
580
+
581
+ if (!$zip_archive_db_result) {
582
+ $this->_log("DB zip, fallback to PclZip");
583
+ $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
584
+ if (!$pclzip_db_result) {
585
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
586
+ @unlink($db_result);
587
+ @rmdir(MWP_DB_DIR);
588
+
589
+ return array(
590
+ 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
591
+ );
592
+ }
593
+ }
594
  }
595
+
596
  @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
597
  @unlink($db_result);
598
  @rmdir(MWP_DB_DIR);
599
 
 
 
 
 
600
  $remove = array(
601
+ trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
602
+ trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
603
  );
604
+ $exclude = array_merge($exclude, $remove);
605
 
606
+ $this->update_status($task_name, $this->statuses['db_zip'], true);
607
+ $this->update_status($task_name, $this->statuses['files_zip']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
 
609
+ $zip_result = $this->zip_backup($task_name, $backup_file, $exclude, $include);
 
 
 
 
 
 
 
 
 
 
610
 
611
+ if (isset($zip_result['error'])) {
612
+ return $zip_result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  }
 
614
 
615
+ if (!$zip_result) {
616
+ $zip_archive_result = false;
617
+ if (class_exists("ZipArchive")) {
618
+ $this->_log("Files zip fallback to ZipArchive");
619
+ $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
620
+ }
621
+
622
+ if (!$zip_archive_result) {
623
+ $this->_log("Files zip fallback to PclZip");
624
+ $pclzip_result = $this->pclzip_backup($task_name, $backup_file, $exclude, $include);
625
+ if (!$pclzip_result) {
626
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
627
+ @unlink($db_result);
628
+ @rmdir(MWP_DB_DIR);
629
+
630
+ if (!$pclzip_result) {
631
+ @unlink($backup_file);
632
+ return array(
633
+ 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
634
+ );
635
+ }
636
+ }
637
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
  }
639
 
640
  //Reconnect
644
  return true;
645
  }
646
 
647
+ /**
648
+ * Zipping database dump and index.php in folder mwp_db by system zip command, requires zip installed on OS.
649
+ *
650
+ * @param string $task_name the name of backup task
651
+ * @param string $backup_file absolute path to zip file
652
+ * @return bool is compress successful or not
653
+ */
654
+ function zip_backup_db($task_name, $backup_file) {
655
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
656
+ $comp_level = $disable_comp ? '-0' : '-1';
657
+ $zip = $this->get_zip();
658
+ //Add database file
659
+ chdir(MWP_BACKUP_DIR);
660
+ $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
661
+
662
+ ob_start();
663
+ $this->_log("Executing $command");
664
+ $result = $this->mmb_exec($command);
665
+ ob_get_clean();
666
+
667
+ return $result;
668
+ }
669
 
670
+ /**
671
+ * Zipping database dump and index.php in folder mwp_db by ZipArchive class, requires php zip extension.
672
+ *
673
+ * @param string $task_name the name of backup task
674
+ * @param string $db_result relative path to database dump file
675
+ * @param string $backup_file absolute path to zip file
676
+ * @return bool is compress successful or not
677
+ */
678
+ function zip_archive_backup_db($task_name, $db_result, $backup_file) {
679
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
680
+ if (!$disable_comp) {
681
+ $this->_log("Compression is not supported by ZipArchive");
682
+ }
683
+ $zip = new ZipArchive();
684
+ $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
685
+ if ($result === true) {
686
+ $result = $result && $zip->addFile(MWP_BACKUP_DIR.'/mwp_db/index.php', "mwp_db/index.php"); // Tries to add mwp_db/index.php to $backup_file
687
+ $result = $result && $zip->addFile($db_result, "mwp_db/" . basename($db_result)); // Tries to add db dump form mwp_db dir to $backup_file
688
+ $result = $result && $zip->close(); // Tries to close $backup_file
689
+ } else {
690
+ $result = false;
691
+ }
692
+
693
+ return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
694
+ }
695
+
696
+ /**
697
+ * Zipping database dump and index.php in folder mwp_db by PclZip library.
698
+ *
699
+ * @param string $task_name the name of backup task
700
+ * @param string $backup_file absolute path to zip file
701
+ * @return bool is compress successful or not
702
+ */
703
+ function pclzip_backup_db($task_name, $backup_file) {
704
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
705
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
706
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
707
+ $zip = new PclZip($backup_file);
708
+
709
+ if ($disable_comp) {
710
+ $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
711
+ } else {
712
+ $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
713
+ }
714
+
715
+ return $result;
716
+ }
717
+
718
+ /**
719
+ * Zipping whole site root folder and append to backup file with database dump
720
+ * by system zip command, requires zip installed on OS.
721
+ *
722
+ * @param string $task_name the name of backup task
723
+ * @param string $backup_file absolute path to zip file
724
+ * @param array $exclude array of files of folders to exclude, relative to site's root
725
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
726
+ * @return array|bool true if successful or an array with error message if not
727
+ */
728
+ function zip_backup($task_name, $backup_file, $exclude, $include) {
729
+ global $zip_errors;
730
+ $sys = substr(PHP_OS, 0, 3);
731
+
732
+ //Exclude paths
733
+ $exclude_data = "-x";
734
+
735
+ $exclude_file_data = '';
736
+
737
+ if (!empty($exclude)) {
738
+ foreach ($exclude as $data) {
739
+ if (is_dir(ABSPATH . $data)) {
740
+ if ($sys == 'WIN')
741
+ $exclude_data .= " $data/*.*";
742
+ else
743
+ $exclude_data .= " '$data/*'";
744
+ } else {
745
+ if ($sys == 'WIN'){
746
+ if(file_exists(ABSPATH . $data)){
747
+ $exclude_data .= " $data";
748
+ $exclude_file_data .= " $data";
749
+ }
750
+ } else {
751
+ if(file_exists(ABSPATH . $data)){
752
+ $exclude_data .= " '$data'";
753
+ $exclude_file_data .= " '$data'";
754
+ }
755
+ }
756
+ }
757
+ }
758
+ }
759
+
760
+ if($exclude_file_data){
761
+ $exclude_file_data = "-x".$exclude_file_data;
762
+ }
763
+
764
+ //Include paths by default
765
+ $add = array(
766
+ trim(WPINC),
767
+ trim(basename(WP_CONTENT_DIR)),
768
+ "wp-admin"
769
+ );
770
+
771
+ $include_data = ". -i";
772
+ foreach ($add as $data) {
773
+ if ($sys == 'WIN')
774
+ $include_data .= " $data/*.*";
775
+ else
776
+ $include_data .= " '$data/*'";
777
+ }
778
+
779
+ //Additional includes?
780
+ if (!empty($include)) {
781
+ foreach ($include as $data) {
782
+ if ($data) {
783
+ if ($sys == 'WIN')
784
+ $include_data .= " $data/*.*";
785
+ else
786
+ $include_data .= " '$data/*'";
787
+ }
788
+ }
789
+ }
790
+
791
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
792
+ $comp_level = $disable_comp ? '-0' : '-1';
793
+ $zip = $this->get_zip();
794
+ chdir(ABSPATH);
795
+ ob_start();
796
+ $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
797
+ $this->_log("Executing $command");
798
+ $result_f = $this->mmb_exec($command, false, true);
799
+ if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
800
+ $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
801
+ $result_d = $this->mmb_exec($command, false, true);
802
+ $this->_log("Executing $command");
803
+ if ($result_d && $result_d != 18) {
804
+ @unlink($backup_file);
805
+ if ($result_d > 0 && $result_d < 18)
806
+ return array(
807
+ 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
808
+ );
809
+ else {
810
+ if ($result_d === -1) return false;
811
+ return array(
812
+ 'error' => 'Failed to archive files.'
813
+ );
814
+ }
815
+ }
816
+ } else {
817
+ return false;
818
+ }
819
+
820
+ ob_get_clean();
821
+
822
+ return true;
823
+ }
824
+
825
+ /**
826
+ * Zipping whole site root folder and append to backup file with database dump
827
+ * by ZipArchive class, requires php zip extension.
828
+ *
829
+ * @param string $task_name the name of backup task
830
+ * @param string $backup_file absolute path to zip file
831
+ * @param array $exclude array of files of folders to exclude, relative to site's root
832
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
833
+ * @return array|bool true if successful or an array with error message if not
834
+ */
835
+ function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
836
+ $filelist = $this->get_backup_files($exclude, $include);
837
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
838
+ if (!$disable_comp) {
839
+ $this->_log("Compression is not supported by ZipArchive");
840
+ }
841
+
842
+ $zip = new ZipArchive();
843
+ if ($overwrite) {
844
+ $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
845
+ } else {
846
+ $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
847
+ }
848
+ if ($result === true) {
849
+ foreach ($filelist as $file) {
850
+ $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
851
+ }
852
+ $result = $result && $zip->close(); // Tries to close $backup_file
853
+ } else {
854
+ $result = false;
855
+ }
856
+
857
+ return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
858
+ }
859
+
860
+ /**
861
+ * Zipping whole site root folder and append to backup file with database dump
862
+ * by PclZip library.
863
+ *
864
+ * @param string $task_name the name of backup task
865
+ * @param string $backup_file absolute path to zip file
866
+ * @param array $exclude array of files of folders to exclude, relative to site's root
867
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
868
+ * @return array|bool true if successful or an array with error message if not
869
+ */
870
+ function pclzip_backup($task_name, $backup_file, $exclude, $include) {
871
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
872
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
873
+ $zip = new PclZip($backup_file);
874
+ $add = array(
875
+ trim(WPINC),
876
+ trim(basename(WP_CONTENT_DIR)),
877
+ "wp-admin"
878
+ );
879
+
880
+ $include_data = array();
881
+ if (!empty($include)) {
882
+ foreach ($include as $data) {
883
+ if ($data && file_exists(ABSPATH . $data))
884
+ $include_data[] = ABSPATH . $data . '/';
885
+ }
886
+ }
887
+ $include_data = array_merge($add, $include_data);
888
+
889
+ if ($handle = opendir(ABSPATH)) {
890
+ while (false !== ($file = readdir($handle))) {
891
+ if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
892
+ $include_data[] = ABSPATH . $file;
893
+ }
894
+ }
895
+ closedir($handle);
896
+ }
897
+
898
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
899
+
900
+ if ($disable_comp) {
901
+ $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION) !== 0;
902
+ } else {
903
+ $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH) !== 0;
904
+ }
905
+
906
+ $exclude_data = array();
907
+ if (!empty($exclude)) {
908
+ foreach ($exclude as $data) {
909
+ if (file_exists(ABSPATH . $data)) {
910
+ if (is_dir(ABSPATH . $data))
911
+ $exclude_data[] = $data . '/';
912
+ else
913
+ $exclude_data[] = $data;
914
+ }
915
+ }
916
+ }
917
+ $result = $result && $zip->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
918
+
919
+ return $result;
920
+ }
921
+
922
+ /**
923
+ * Gets an array of relative paths of all files in site root recursively.
924
+ * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
925
+ * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
926
+ *
927
+ * @param array $exclude array of files of folders to exclude, relative to site's root
928
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
929
+ * @return array array with all files in site root dir
930
+ */
931
+ function get_backup_files($exclude, $include) {
932
+ $add = array(
933
+ trim(WPINC),
934
+ trim(basename(WP_CONTENT_DIR)),
935
+ "wp-admin"
936
+ );
937
+
938
+ $include = array_merge($add, $include);
939
+
940
+ $filelist = array();
941
+ if ($handle = opendir(ABSPATH)) {
942
+ while (false !== ($file = readdir($handle))) {
943
+ if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
944
+ $exclude[] = $file;
945
+ }
946
+ }
947
+ closedir($handle);
948
+ }
949
+
950
+ $filelist = get_all_files_from_dir(ABSPATH, $exclude);
951
+
952
+ return $filelist;
953
+ }
954
+
955
+ /**
956
+ * Backup a database dump of WordPress site.
957
+ * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
958
+ *
959
+ * @param string $task_name the name of backup task, which backup is done
960
+ * @param string $backup_file relative path to file which backup is stored
961
+ * @return bool|array true if backup is successful, or an array with error message if is failed
962
+ */
963
+ function backup_db_compress($task_name, $backup_file) {
964
+ $this->update_status($task_name, $this->statuses['db_dump']);
965
+ $db_result = $this->backup_db();
966
+
967
+ if ($db_result == false) {
968
+ return array(
969
+ 'error' => 'Failed to backup database.'
970
+ );
971
+ } else if (is_array($db_result) && isset($db_result['error'])) {
972
+ return array(
973
+ 'error' => $db_result['error']
974
+ );
975
+ }
976
+
977
+ $this->update_status($task_name, $this->statuses['db_dump'], true);
978
+ $this->update_status($task_name, $this->statuses['db_zip']);
979
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
980
+ $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
981
+
982
+ if (!$zip_db_result) {
983
+ $zip_archive_db_result = false;
984
+ if (class_exists("ZipArchive")) {
985
+ $this->_log("DB zip, fallback to ZipArchive");
986
+ $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
987
+ }
988
+
989
+ if (!$zip_archive_db_result) {
990
+ $this->_log("DB zip, fallback to PclZip");
991
+ $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
992
+ if (!$pclzip_db_result) {
993
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
994
+ @unlink($db_result);
995
+ @rmdir(MWP_DB_DIR);
996
+
997
+ return array(
998
+ 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
999
+ );
1000
+ }
1001
+ }
1002
+ }
1003
+
1004
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
1005
+ @unlink($db_result);
1006
+ @rmdir(MWP_DB_DIR);
1007
+
1008
+ $this->update_status($task_name, $this->statuses['db_zip'], true);
1009
+
1010
+ return true;
1011
+ }
1012
+
1013
+ /**
1014
+ * Creates database dump and places it in mwp_db folder in site's root.
1015
+ * This function dispatches if OS mysql command does not work calls a php alternative.
1016
+ *
1017
+ * @return string|array path to dump file if successful, or an array with error message if is failed
1018
+ */
1019
+ function backup_db() {
1020
  $db_folder = MWP_DB_DIR . '/';
1021
  if (!file_exists($db_folder)) {
1022
  if (!mkdir($db_folder, 0755, true))
1030
  return $result;
1031
  }
1032
 
1033
+ /**
1034
+ * Creates database dump by system mysql command.
1035
+ *
1036
+ * @param string $file absolute path to file in which dump should be placed
1037
+ * @return string|array path to dump file if successful, or an array with error message if is failed
1038
+ */
1039
+ function backup_db_dump($file) {
1040
  global $wpdb;
1041
  $paths = $this->check_mysql_paths();
1042
  $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1059
  }
1060
  }
1061
 
1062
+ /**
1063
+ * Creates database dump by php functions.
1064
+ *
1065
+ * @param string $file absolute path to file in which dump should be placed
1066
+ * @return string|array path to dump file if successful, or an array with error message if is failed
1067
+ */
1068
+ function backup_db_php($file) {
1069
  global $wpdb;
1070
  $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1071
  foreach ($tables as $table) {
1080
  $count = ceil($count / 100);
1081
  else if ($count > 0)
1082
  $count = 1;
1083
+
1084
  for ($i = 0; $i < $count; $i++) {
1085
  $low_limit = $i * 100;
1086
  $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
1117
  }
1118
 
1119
  return $file;
 
1120
  }
1121
 
1122
+ /**
1123
+ * Restores full WordPress site or database only form backup zip file.
1124
+ *
1125
+ * @param array array of arguments passed to backup restore
1126
+ * [task_name] -> name of backup task
1127
+ * [result_id] -> id of baskup task result, which should be restored
1128
+ * [google_drive_token] -> json of Google Drive token, if it is remote destination
1129
+ * @return bool|array true if successful, or an array with error message if is failed
1130
+ */
1131
  function restore($args) {
1132
  global $wpdb;
1133
  if (empty($args)) {
1139
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
1140
  }
1141
  $this->set_memory();
1142
+
1143
  $unlink_file = true; //Delete file after restore
1144
 
1145
  //Detect source
1164
  $args = $task['task_args']['account_info']['mwp_ftp'];
1165
  $args['backup_file'] = $ftp_file;
1166
  $backup_file = $this->get_ftp_backup($args);
1167
+
1168
  if ($backup_file == false) {
1169
  return array(
1170
  'error' => 'Failed to download file from FTP.'
1175
  $args = $task['task_args']['account_info']['mwp_amazon_s3'];
1176
  $args['backup_file'] = $amazons3_file;
1177
  $backup_file = $this->get_amazons3_backup($args);
1178
+
1179
  if ($backup_file == false) {
1180
  return array(
1181
  'error' => 'Failed to download file from Amazon S3.'
1209
  }
1210
  }
1211
 
 
1212
  $what = $tasks[$task_name]['task_args']['what'];
1213
  }
1214
 
1232
 
1233
  $clone_options = array();
1234
  if (trim($clone_from_url) || trim($mwp_clone)) {
 
1235
  $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
1236
  $clone_options['_worker_public_key'] = get_option('_worker_public_key');
1237
  $clone_options['_action_message_id'] = get_option('_action_message_id');
 
1238
  }
1239
+ $clone_options['upload_path'] = get_option('upload_path');
1240
+ $clone_options['upload_url_path'] = get_option('upload_url_path');
 
 
 
 
 
1241
 
1242
+ $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
1243
+ $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
1244
+ $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
1245
  } else {
1246
  $restore_options = array();
1247
+ $restore_options['mwp_notifications'] = get_option('mwp_notifications');
1248
+ $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
1249
+ $restore_options['user_hit_count'] = get_option('user_hit_count');
1250
  }
1251
 
 
1252
  chdir(ABSPATH);
1253
  $unzip = $this->get_unzip();
1254
  $command = "$unzip -o $backup_file";
1276
 
1277
  $db_result = $this->restore_db();
1278
 
1279
+ if (!$db_result) {
1280
  return array(
1281
  'error' => 'Error restoring database.'
1282
  );
1379
  //Check for .htaccess permalinks update
1380
  $this->replace_htaccess($home);
1381
  } else {
1382
+ //restore worker options
1383
+ if (is_array($restore_options) && !empty($restore_options)) {
 
1384
  foreach ($restore_options as $key => $option) {
1385
  update_option($key,$option);
1386
  }
1387
+ }
 
1388
  }
1389
 
 
 
 
1390
  return true;
1391
  }
1392
 
1393
+ /**
1394
+ * This function dispathces database restoring between mysql system command and php functions.
1395
+ * If system command fails, it calls the php alternative.
1396
+ *
1397
+ * @return bool|array true if successful, array with error message if not
1398
+ */
1399
+ function restore_db() {
1400
  global $wpdb;
1401
  $paths = $this->check_mysql_paths();
1402
  $file_path = ABSPATH . 'mwp_db';
1420
  $this->restore_db_php($file_name);
1421
  }
1422
 
 
1423
  @unlink($file_name);
1424
  return true;
1425
  }
1426
 
1427
+ /**
1428
+ * Restores database dump by php functions.
1429
+ *
1430
+ * @param string $file_name relative path to database dump, which should be restored
1431
+ * @return bool is successful or not
1432
+ */
1433
+ function restore_db_php($file_name) {
1434
  global $wpdb;
1435
  $current_query = '';
1436
  // Read in entire file
1458
  return true;
1459
  }
1460
 
1461
+ /**
1462
+ * Retruns table_prefix for this WordPress installation.
1463
+ * It is used by restore.
1464
+ *
1465
+ * @return string table prefix from wp-config.php file, (default: wp_)
1466
+ */
1467
+ function get_table_prefix() {
1468
  $lines = file(ABSPATH . 'wp-config.php');
1469
  foreach ($lines as $line) {
1470
  if (strstr($line, '$table_prefix')) {
1478
  return 'wp_'; //default
1479
  }
1480
 
1481
+ /**
1482
+ * Change all tables to InnoDB engine, and executes mysql OPTIMIZE TABLE for each table.
1483
+ *
1484
+ * @return bool optimized successfully or not
1485
+ */
1486
+ function optimize_tables() {
1487
  global $wpdb;
1488
  $query = 'SHOW TABLES';
1489
  $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1507
  return $optimize ? true : false;
1508
  }
1509
 
1510
+ /**
1511
+ * Returns mysql and mysql dump command path on OS.
1512
+ *
1513
+ * @return array array with system mysql and mysqldump command, blank if does not exist
1514
+ */
1515
+ function check_mysql_paths() {
1516
  global $wpdb;
1517
  $paths = array(
1518
  'mysql' => '',
1535
 
1536
  $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1537
  if (empty($paths['mysqldump']))
1538
+ $paths['mysqldump'] = 'mysqldump'; // try anyway
 
1539
  }
1540
 
 
1541
  return $paths;
1542
  }
1543
 
1544
+ /**
1545
+ * Check if exec, system, passthru functions exist
1546
+ *
1547
+ * @return string|bool exec if exists, then system, then passthru, then false if no one exist
1548
+ */
1549
+ function check_sys() {
1550
  if ($this->mmb_function_exists('exec'))
1551
  return 'exec';
1552
 
1557
  return 'passthru';
1558
 
1559
  return false;
 
1560
  }
1561
 
1562
+ /**
1563
+ * Executes an external system command.
1564
+ *
1565
+ * @param string $command external command to execute
1566
+ * @param bool[optional] $string return as a system output string (default: false)
1567
+ * @param bool[optional] $rawreturn return as a status of executed command
1568
+ * @return bool|int|string output depends on parameters $string and $rawreturn, -1 if no one execute function is enabled
1569
+ */
1570
+ function mmb_exec($command, $string = false, $rawreturn = false) {
1571
  if ($command == '')
1572
  return false;
1573
 
1607
 
1608
  if ($rawreturn)
1609
  return -1;
1610
+
1611
  return false;
1612
  }
1613
 
1614
+ /**
1615
+ * Returns a path to system command for zip execution.
1616
+ *
1617
+ * @return string command for zip execution
1618
+ */
1619
+ function get_zip() {
1620
  $zip = $this->mmb_exec('which zip', true);
1621
  if (!$zip)
1622
  $zip = "zip";
1623
  return $zip;
1624
  }
1625
 
1626
+ /**
1627
+ * Returns a path to system command for unzip execution.
1628
+ *
1629
+ * @return string command for unzip execution
1630
+ */
1631
+ function get_unzip() {
1632
  $unzip = $this->mmb_exec('which unzip', true);
1633
  if (!$unzip)
1634
  $unzip = "unzip";
1635
  return $unzip;
1636
  }
1637
 
1638
+ /**
1639
+ * Returns all important information of worker's system status to master.
1640
+ *
1641
+ * @return mixed associative array with information of server OS, php version, is backup folder writable, execute function, zip and unzip command, execution time, memory limit and path to error log if exists
1642
+ */
1643
+ function check_backup_compat() {
1644
+ $reqs = array();
1645
  if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1646
  $reqs['Server OS']['status'] = 'Linux (or compatible)';
1647
  $reqs['Server OS']['pass'] = true;
1658
  $pass = false;
1659
  }
1660
 
 
1661
  if (is_writable(WP_CONTENT_DIR)) {
1662
  $reqs['Backup Folder']['status'] = "writable";
1663
  $reqs['Backup Folder']['pass'] = true;
1666
  $reqs['Backup Folder']['pass'] = false;
1667
  }
1668
 
 
1669
  $file_path = MWP_BACKUP_DIR;
1670
  $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1671
 
1677
  $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1678
  $reqs['Execute Function']['pass'] = false;
1679
  }
 
1680
 
1681
+ $reqs['Zip']['status'] = $this->get_zip();
1682
  $reqs['Zip']['pass'] = true;
 
 
 
1683
  $reqs['Unzip']['status'] = $this->get_unzip();
 
1684
  $reqs['Unzip']['pass'] = true;
1685
 
1686
  $paths = $this->check_mysql_paths();
1727
  return $reqs;
1728
  }
1729
 
1730
+ /**
1731
+ * Uploads backup file from server to email.
1732
+ * A lot of email service have limitation to 10mb.
1733
+ *
1734
+ * @param array $args arguments passed to the function
1735
+ * [email] -> email address which backup should send to
1736
+ * [task_name] -> name of backup task
1737
+ * [file_path] -> absolute path of backup file on local server
1738
+ * @return bool|array true is successful, array with error message if not
1739
+ */
1740
+ function email_backup($args) {
1741
  $email = $args['email'];
1742
 
1743
  if (!is_email($email)) {
1765
  );
1766
  }
1767
  return true;
 
1768
  }
1769
 
1770
+ /**
1771
+ * Uploads backup file from server to remote ftp server.
1772
+ *
1773
+ * @param array $args arguments passed to the function
1774
+ * [ftp_username] -> ftp username on remote server
1775
+ * [ftp_password] -> ftp password on remote server
1776
+ * [ftp_hostname] -> ftp hostname of remote host
1777
+ * [ftp_remote_folder] -> folder on remote site which backup file should be upload to
1778
+ * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be upload to
1779
+ * [backup_file] -> absolute path of backup file on local server
1780
+ * @return bool|array true is successful, array with error message if not
1781
+ */
1782
+ function ftp_backup($args) {
1783
  extract($args);
1784
+
1785
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1786
  if ($ftp_ssl) {
1787
  if (function_exists('ftp_ssl_connect')) {
1817
  }
1818
 
1819
  if($ftp_passive){
1820
+ @ftp_pasv($conn_id,true);
1821
+ }
1822
+
1823
  @ftp_mkdir($conn_id, $ftp_remote_folder);
1824
  if ($ftp_site_folder) {
1825
  $ftp_remote_folder .= '/' . $this->site_name;
1826
  }
1827
  @ftp_mkdir($conn_id, $ftp_remote_folder);
1828
+
1829
  $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1830
  if ($upload === false) { //Try ascii
1831
  $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1842
  return true;
1843
  }
1844
 
1845
+ /**
1846
+ * Deletes backup file from remote ftp server.
1847
+ *
1848
+ * @param array $args arguments passed to the function
1849
+ * [ftp_username] -> ftp username on remote server
1850
+ * [ftp_password] -> ftp password on remote server
1851
+ * [ftp_hostname] -> ftp hostname of remote host
1852
+ * [ftp_remote_folder] -> folder on remote site which backup file should be deleted from
1853
+ * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be deleted from
1854
+ * [backup_file] -> absolute path of backup file on local server
1855
+ * @return void
1856
+ */
1857
+ function remove_ftp_backup($args) {
1858
  extract($args);
1859
+
1860
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1861
  if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1862
  $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1870
  $ftp_remote_folder .= '/' . $this->site_name;
1871
 
1872
  if($ftp_passive){
1873
+ @ftp_pasv($conn_id,true);
1874
+ }
1875
+
1876
  $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1877
 
1878
  ftp_close($conn_id);
1879
  }
 
1880
  }
1881
 
1882
+ /**
1883
+ * Downloads backup file from server from remote ftp server to root folder on local server.
1884
+ *
1885
+ * @param array $args arguments passed to the function
1886
+ * [ftp_username] -> ftp username on remote server
1887
+ * [ftp_password] -> ftp password on remote server
1888
+ * [ftp_hostname] -> ftp hostname of remote host
1889
+ * [ftp_remote_folder] -> folder on remote site which backup file should be downloaded from
1890
+ * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be downloaded from
1891
+ * [backup_file] -> absolute path of backup file on local server
1892
+ * @return string|array absolute path to downloaded file is successful, array with error message if not
1893
+ */
1894
+ function get_ftp_backup($args) {
1895
  extract($args);
1896
+
1897
  $port = $ftp_port ? $ftp_port : 21; //default port is 21
1898
  if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1899
  $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1900
+
1901
  } else if (function_exists('ftp_connect')) {
1902
  $conn_id = ftp_connect($ftp_hostname,$port);
1903
  if ($conn_id === false) {
1907
  $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1908
  if ($login === false) {
1909
  return false;
 
1910
  }
1911
 
1912
  if ($ftp_site_folder)
1913
  $ftp_remote_folder .= '/' . $this->site_name;
1914
 
1915
  if($ftp_passive){
1916
+ @ftp_pasv($conn_id,true);
1917
+ }
1918
 
1919
  $temp = ABSPATH . 'mwp_temp_backup.zip';
1920
  $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1921
  if ($get === false) {
1922
  return false;
 
1923
  }
1924
+
1925
  ftp_close($conn_id);
1926
 
1927
  return $temp;
1928
  }
1929
 
1930
+ /**
1931
+ * Uploads backup file from server to Dropbox.
1932
+ *
1933
+ * @param array $args arguments passed to the function
1934
+ * [consumer_key] -> consumer key of ManageWP Dropbox application
1935
+ * [consumer_secret] -> consumer secret of ManageWP Dropbox application
1936
+ * [oauth_token] -> oauth token of user on ManageWP Dropbox application
1937
+ * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
1938
+ * [dropbox_destination] -> folder on user's Dropbox account which backup file should be upload to
1939
+ * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be upload to
1940
+ * [backup_file] -> absolute path of backup file on local server
1941
+ * @return bool|array true is successful, array with error message if not
1942
+ */
1943
+ function dropbox_backup($args) {
1944
  extract($args);
1945
 
1946
+ global $mmb_plugin_dir;
1947
+ require_once $mmb_plugin_dir . '/lib/dropbox.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1948
 
1949
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
1950
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
 
 
 
 
 
1951
 
1952
  if ($dropbox_site_folder == true)
1953
+ $dropbox_destination .= '/' . $this->site_name . '/' . basename($backup_file);
1954
+ else
1955
+ $dropbox_destination .= '/' . basename($backup_file);
1956
 
1957
  try {
1958
+ $dropbox->upload($backup_file, $dropbox_destination, true);
1959
+ } catch (Exception $e) {
1960
+ $this->_log($e->getMessage());
1961
+ return array(
1962
+ 'error' => $e->getMessage(),
1963
+ 'partial' => 1
1964
+ );
 
1965
  }
1966
 
1967
  return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1968
  }
1969
 
1970
+ /**
1971
+ * Deletes backup file from Dropbox to root folder on local server.
1972
+ *
1973
+ * @param array $args arguments passed to the function
1974
+ * [consumer_key] -> consumer key of ManageWP Dropbox application
1975
+ * [consumer_secret] -> consumer secret of ManageWP Dropbox application
1976
+ * [oauth_token] -> oauth token of user on ManageWP Dropbox application
1977
+ * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
1978
+ * [dropbox_destination] -> folder on user's Dropbox account which backup file should be downloaded from
1979
+ * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be downloaded from
1980
+ * [backup_file] -> absolute path of backup file on local server
1981
+ * @return void
1982
+ */
1983
+ function remove_dropbox_backup($args) {
1984
+ extract($args);
1985
+
1986
+ global $mmb_plugin_dir;
1987
+ require_once $mmb_plugin_dir . '/lib/dropbox.php';
1988
+
1989
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
1990
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
1991
+
1992
+ if ($dropbox_site_folder == true)
1993
+ $dropbox_destination .= '/' . $this->site_name;
1994
+
1995
+ try {
1996
+ $dropbox->fileopsDelete($dropbox_destination . '/' . $backup_file);
1997
+ } catch (Exception $e) {
1998
+ $this->_log($e->getMessage());
1999
+ /*return array(
2000
+ 'error' => $e->getMessage(),
2001
+ 'partial' => 1
2002
+ );*/
2003
+ }
2004
+
2005
+ //return true;
2006
+ }
2007
+
2008
+ /**
2009
+ * Downloads backup file from Dropbox to root folder on local server.
2010
+ *
2011
+ * @param array $args arguments passed to the function
2012
+ * [consumer_key] -> consumer key of ManageWP Dropbox application
2013
+ * [consumer_secret] -> consumer secret of ManageWP Dropbox application
2014
+ * [oauth_token] -> oauth token of user on ManageWP Dropbox application
2015
+ * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
2016
+ * [dropbox_destination] -> folder on user's Dropbox account which backup file should be deleted from
2017
+ * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be deleted from
2018
+ * [backup_file] -> absolute path of backup file on local server
2019
+ * @return bool|array absolute path to downloaded file is successful, array with error message if not
2020
+ */
2021
+ function get_dropbox_backup($args) {
2022
+ extract($args);
2023
+
2024
+ global $mmb_plugin_dir;
2025
+ require_once $mmb_plugin_dir . '/lib/dropbox.php';
2026
+
2027
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
2028
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2029
+
2030
+ if ($dropbox_site_folder == true)
2031
+ $dropbox_destination .= '/' . $this->site_name;
2032
+
2033
+ $temp = ABSPATH . 'mwp_temp_backup.zip';
2034
+
2035
+ try {
2036
+ $file = $dropbox->download($dropbox_destination.'/'.$backup_file);
2037
+ $handle = @fopen($temp, 'w');
2038
+ $result = fwrite($handle,$file);
2039
+ fclose($handle);
2040
+
2041
+ if($result)
2042
+ return $temp;
2043
+ else
2044
+ return false;
2045
+ } catch (Exception $e) {
2046
+ $this->_log($e->getMessage());
2047
+ return array(
2048
+ 'error' => $e->getMessage(),
2049
+ 'partial' => 1
2050
+ );
2051
+ }
2052
+ }
2053
+
2054
+ /**
2055
+ * Uploads backup file from server to Amazon S3.
2056
+ *
2057
+ * @param array $args arguments passed to the function
2058
+ * [as3_bucket_region] -> Amazon S3 bucket region
2059
+ * [as3_bucket] -> Amazon S3 bucket
2060
+ * [as3_access_key] -> Amazon S3 access key
2061
+ * [as3_secure_key] -> Amazon S3 secure key
2062
+ * [as3_directory] -> folder on user's Amazon S3 account which backup file should be upload to
2063
+ * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be upload to
2064
+ * [backup_file] -> absolute path of backup file on local server
2065
+ * @return bool|array true is successful, array with error message if not
2066
+ */
2067
+ function amazons3_backup($args) {
2068
  if ($this->mmb_function_exists('curl_init')) {
2069
  require_once('lib/s3.php');
2070
  extract($args);
2074
 
2075
  $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2076
  try{
2077
+ $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
2078
+ if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
2079
+ return true;
2080
+ } else {
2081
+
2082
+ return array(
2083
+ 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
2084
+ 'partial' => 1
2085
+ );
2086
+ }
2087
+ } catch (Exception $e) {
2088
+ $err = $e->getMessage();
2089
+ if($err){
2090
+ return array(
2091
+ 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
2092
+ );
2093
+ } else {
2094
+ return array(
2095
+ 'error' => 'Failed to upload to Amazon S3.'
2096
+ );
2097
+ }
2098
+ }
 
2099
 
2100
  } else {
2101
  return array(
2105
  }
2106
  }
2107
 
2108
+ /**
2109
+ * Deletes backup file from Amazon S3.
2110
+ *
2111
+ * @param array $args arguments passed to the function
2112
+ * [as3_bucket_region] -> Amazon S3 bucket region
2113
+ * [as3_bucket] -> Amazon S3 bucket
2114
+ * [as3_access_key] -> Amazon S3 access key
2115
+ * [as3_secure_key] -> Amazon S3 secure key
2116
+ * [as3_directory] -> folder on user's Amazon S3 account which backup file should be deleted from
2117
+ * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be deleted from
2118
+ * [backup_file] -> absolute path of backup file on local server
2119
+ * @return void
2120
+ */
2121
+ function remove_amazons3_backup($args) {
2122
  if ($this->mmb_function_exists('curl_init')) {
2123
+ require_once('lib/s3.php');
2124
+ extract($args);
2125
+ if ($as3_site_folder == true)
2126
+ $as3_directory .= '/' . $this->site_name;
2127
+ $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2128
+ try {
2129
+ $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
2130
+ $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
2131
+ } catch (Exception $e){
2132
+
2133
+ }
2134
+ }
2135
  }
2136
 
2137
+ /**
2138
+ * Downloads backup file from Amazon S3 to root folder on local server.
2139
+ *
2140
+ * @param array $args arguments passed to the function
2141
+ * [as3_bucket_region] -> Amazon S3 bucket region
2142
+ * [as3_bucket] -> Amazon S3 bucket
2143
+ * [as3_access_key] -> Amazon S3 access key
2144
+ * [as3_secure_key] -> Amazon S3 secure key
2145
+ * [as3_directory] -> folder on user's Amazon S3 account which backup file should be downloaded from
2146
+ * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be downloaded from
2147
+ * [backup_file] -> absolute path of backup file on local server
2148
+ * @return bool|array absolute path to downloaded file is successful, array with error message if not
2149
+ */
2150
+ function get_amazons3_backup($args) {
2151
  require_once('lib/s3.php');
2152
  extract($args);
2153
  $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2154
  $temp = '';
2155
+ try {
2156
+ $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
2157
+ if ($as3_site_folder == true)
2158
+ $as3_directory .= '/' . $this->site_name;
2159
+
2160
+ $temp = ABSPATH . 'mwp_temp_backup.zip';
2161
+ $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
2162
+ } catch (Exception $e) {
2163
+ return $temp;
2164
+ }
2165
+ return $temp;
2166
  }
2167
 
2168
+ /**
2169
+ * Uploads backup file from server to Google Drive.
2170
+ *
2171
+ * @param array $args arguments passed to the function
2172
+ * [google_drive_token] -> user's Google drive token in json form
2173
+ * [google_drive_directory] -> folder on user's Google Drive account which backup file should be upload to
2174
+ * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be upload to
2175
+ * [backup_file] -> absolute path of backup file on local server
2176
+ * @return bool|array true is successful, array with error message if not
2177
  */
2178
  function google_drive_backup($args) {
2179
  extract($args);
2214
  $_managewp_folder = new Google_DriveFile();
2215
  $_managewp_folder->setTitle($google_drive_directory);
2216
  $_managewp_folder->setMimeType('application/vnd.google-apps.folder');
2217
+
2218
  if ($root_folder_id != null) {
2219
  $parent = new Google_ParentReference();
2220
  $parent->setId($root_folder_id);
2271
  if ($backup_folder != null) {
2272
  $new_file->setParents(array($backup_folder));
2273
  }
2274
+
2275
+ $tries = 1;
2276
+
2277
+ while($tries <= 2) {
2278
+ try {
2279
+ $data = file_get_contents($backup_file);
2280
+
2281
+ $createdFile = $gdrive_service->files->insert($new_file, array(
2282
+ 'data' => $data,
2283
+ ));
2284
+
2285
+ break;
2286
+ } catch (Exception $e) {
2287
+ if ($e->getCode() >= 500 && $e->getCode() <= 504 && $mmb_gdrive_upload_tries <= 2) {
2288
+ sleep(2);
2289
+ $tries++;
2290
+ } else {
2291
+ return array(
2292
+ 'error' => $e->getMessage(),
2293
+ );
2294
+ }
2295
+ }
2296
  }
2297
 
2298
  return true;
2299
  }
2300
 
2301
+ /**
2302
+ * Deletes backup file from Google Drive.
2303
+ *
2304
+ * @param array $args arguments passed to the function
2305
+ * [google_drive_token] -> user's Google drive token in json form
2306
+ * [google_drive_directory] -> folder on user's Google Drive account which backup file should be deleted from
2307
+ * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be deleted from
2308
+ * [backup_file] -> absolute path of backup file on local server
2309
+ * @return void
2310
+ */
2311
  function remove_google_drive_backup($args) {
2312
  extract($args);
2313
 
2321
  $gdrive_client->setAccessToken($google_drive_token);
2322
  } catch (Exception $e) {
2323
  $this->_log($e->getMessage());
2324
+ /*eturn array(
2325
  'error' => $e->getMessage(),
2326
+ );*/
2327
  }
2328
+
2329
  $gdrive_service = new Google_DriveService($gdrive_client);
2330
 
2331
  try {
2333
  $root_folder_id = $about->getRootFolderId();
2334
  } catch (Exception $e) {
2335
  $this->_log($e->getMessage());
2336
+ /*return array(
2337
  'error' => $e->getMessage(),
2338
+ );*/
2339
  }
2340
 
2341
  try {
2343
  $files = $list_files->getItems();
2344
  } catch (Exception $e) {
2345
  $this->_log($e->getMessage());
2346
+ /*return array(
2347
  'error' => $e->getMessage(),
2348
+ );*/
2349
  }
2350
  if (isset($files[0])) {
2351
  $managewp_folder = $files[0];
2352
  } else {
2353
  $this->_log("This file does not exist.");
2354
+ /*return array(
2355
  'error' => "This file does not exist.",
2356
+ );*/
2357
  }
2358
 
2359
  if ($google_drive_site_folder) {
2364
  $files = $list_files->getItems();
2365
  } catch (Exception $e) {
2366
  $this->_log($e->getMessage());
2367
+ /*return array(
2368
  'error' => $e->getMessage(),
2369
+ );*/
2370
  }
2371
  if (isset($files[0])) {
2372
  $backup_folder = $files[0];
2382
  $files = $list_files->getItems();;
2383
  } catch (Exception $e) {
2384
  $this->_log($e->getMessage());
2385
+ /*return array(
2386
  'error' => $e->getMessage(),
2387
+ );*/
2388
  }
2389
  if (isset($files[0])) {
2390
  try {
2391
  $gdrive_service->files->delete($files[0]->getId());
2392
  } catch (Exception $e) {
2393
  $this->_log($e->getMessage());
2394
+ /*return array(
2395
  'error' => $e->getMessage(),
2396
+ );*/
2397
  }
2398
  } else {
2399
  $this->_log("This file does not exist.");
2400
+ /*return array(
2401
  'error' => "This file does not exist.",
2402
+ );*/
2403
  }
2404
  } else {
2405
  $this->_log("This file does not exist.");
2406
+ /*return array(
2407
  'error' => "This file does not exist.",
2408
+ );*/
2409
  }
2410
 
2411
+ //return true;
2412
  }
2413
 
2414
+ /**
2415
+ * Downloads backup file from Google Drive to root folder on local server.
2416
+ *
2417
+ * @param array $args arguments passed to the function
2418
+ * [google_drive_token] -> user's Google drive token in json form
2419
+ * [google_drive_directory] -> folder on user's Google Drive account which backup file should be downloaded from
2420
+ * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be downloaded from
2421
+ * [backup_file] -> absolute path of backup file on local server
2422
+ * @return bool|array absolute path to downloaded file is successful, array with error message if not
2423
+ */
2424
  function get_google_drive_backup($args) {
2425
  extract($args);
2426
 
2482
  } else {
2483
  $backup_folder = $managewp_folder;
2484
  }
2485
+
2486
  if (isset($backup_folder)) {
2487
  try {
2488
  $backup_folder_id = $backup_folder->getId();
2540
  return false;
2541
  }
2542
 
2543
+ /**
2544
+ * Schedules the next execution of some backup task.
2545
+ *
2546
+ * @param string $type daily, weekly or monthly
2547
+ * @param string $schedule format: task_time (if daily), task_time|task_day (if weekly), task_time|task_date (if monthly)
2548
+ * @return bool|int timestamp if sucessful, false if not
2549
+ */
2550
+ function schedule_next($type, $schedule) {
2551
  $schedule = explode("|", $schedule);
2552
 
2553
  if (empty($schedule))
2554
  return false;
2555
  switch ($type) {
 
2556
  case 'daily':
 
2557
  if (isset($schedule[1]) && $schedule[1]) {
2558
  $delay_time = $schedule[1] * 60;
2559
  }
2566
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2567
  break;
2568
 
 
2569
  case 'weekly':
2570
  if (isset($schedule[2]) && $schedule[2]) {
2571
  $delay_time = $schedule[2] * 60;
2580
  else
2581
  $weekday_offset = $schedule_weekday - $current_weekday;
2582
 
 
2583
  if (!$weekday_offset) { //today is scheduled weekday
2584
  if ($current_hour >= $schedule_hour)
2585
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
2588
  } else {
2589
  $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
2590
  }
 
2591
  break;
2592
+
2593
  case 'monthly':
2594
  if (isset($schedule[2]) && $schedule[2]) {
2595
  $delay_time = $schedule[2] * 60;
2612
  }
2613
 
2614
  break;
2615
+
2616
  default:
2617
  break;
2618
  }
2622
  }
2623
 
2624
  return $time;
 
2625
  }
2626
 
2627
+ /**
2628
+ * Parse task arguments for info on master.
2629
+ *
2630
+ * @return mixed associative array with stats for every backup task or error if backup is manually deleted on server
2631
+ */
2632
+ function get_backup_stats() {
2633
  $stats = array();
2634
  $tasks = $this->tasks;
2635
  if (is_array($tasks) && !empty($tasks)) {
2637
  if (is_array($info['task_results']) && !empty($info['task_results'])) {
2638
  foreach ($info['task_results'] as $key => $result) {
2639
  if (isset($result['server']) && !isset($result['error'])) {
2640
+ if (isset($result['server']['file_path']) && !$info['task_args']['del_host_file']) {
2641
+ if (!file_exists($result['server']['file_path'])) {
2642
+ $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
2643
+ }
2644
  }
2645
  }
2646
  }
2647
  }
2648
  if (is_array($info['task_results']))
2649
  $stats[$task_name] = array_values($info['task_results']);
 
2650
  }
2651
  }
2652
  return $stats;
2653
  }
2654
 
2655
+ /**
2656
+ * Returns all backup tasks with information when the next schedule will be.
2657
+ *
2658
+ * @return mixed associative array with timestamp with next schedule for every backup task
2659
+ */
2660
+ function get_next_schedules() {
2661
  $stats = array();
2662
  $tasks = $this->tasks;
2663
  if (is_array($tasks) && !empty($tasks)) {
2668
  return $stats;
2669
  }
2670
 
2671
+ /**
2672
+ * Deletes all old backups from local server.
2673
+ * It depends on configuration on master (Number of backups to keep).
2674
+ *
2675
+ * @param string $task_name name of backup task
2676
+ * @return bool|void true if there are backups for deletion, void if not
2677
+ */
2678
+ function remove_old_backups($task_name) {
2679
  //Check for previous failed backups first
2680
  $this->cleanup();
2681
 
2687
  $num = 1;
2688
  }
2689
 
 
2690
  if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
2691
  //how many to remove ?
2692
  $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
2716
  $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
2717
  $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
2718
  $args['backup_file'] = $dropbox_file;
2719
+ $this->remove_dropbox_backup($args);
2720
  }
2721
 
2722
  if (isset($backups[$task_name]['task_results'][$i]['google_drive']) && isset($backups[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
2726
  $this->remove_google_drive_backup($args);
2727
  }
2728
 
 
2729
  //Remove database backup info
2730
  unset($backups[$task_name]['task_results'][$i]);
2731
  } //end foreach
2734
  $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
2735
  else
2736
  $backups[$task_name]['task_results']=array();
2737
+
2738
  $this->update_tasks($backups);
 
2739
 
2740
  return true;
2741
  }
2742
  }
2743
 
2744
  /**
2745
+ * Deletes specified backup.
2746
+ *
2747
+ * @param array $args arguments passed to function
2748
+ * [task_name] -> name of backup task
2749
+ * [result_id] -> id of baskup task result, which should be restored
2750
+ * [google_drive_token] -> json of Google Drive token, if it is remote destination
2751
+ * @return bool true if successful, false if not
2752
  */
 
2753
  function delete_backup($args) {
2754
  if (empty($args))
2755
  return false;
2796
  $this->remove_google_drive_backup($args);
2797
  }
2798
 
 
2799
  unset($backups[$result_id]);
2800
 
2801
  if (count($backups)) {
2807
  $this->update_tasks($tasks);
2808
  //update_option('mwp_backup_tasks', $tasks);
2809
  return true;
 
2810
  }
2811
 
2812
+ /**
2813
+ * Deletes all unneeded files produced by backup process.
2814
+ *
2815
+ * @return array array of deleted files
2816
+ */
2817
+ function cleanup() {
2818
  $tasks = $this->tasks;
2819
  $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
2820
  $backup_folder_new = MWP_BACKUP_DIR . '/';
2832
  @rmdir(MWP_DB_DIR);
2833
  }
2834
 
 
2835
  //clean_old folder?
2836
  if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
2837
  foreach ($files as $file) {
2841
  @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
2842
  }
2843
 
 
2844
  foreach ($new as $b) {
2845
  $files[] = $b;
2846
  }
2870
  }
2871
  }
2872
 
 
 
2873
  return $deleted;
2874
  }
2875
 
2876
+ /**
2877
+ * Uploads to remote destination in the second step, invoked from master.
2878
+ *
2879
+ * @param array $args arguments passed to function
2880
+ * [task_name] -> name of backup task
2881
+ * @return array|void void if success, array with error message if not
2882
+ */
2883
  function remote_backup_now($args) {
2884
  $this->set_memory();
2885
  if (!empty($args))
2886
  extract($args);
2887
 
2888
  $tasks = $this->tasks;
2889
+ $task = $tasks[$task_name];
2890
 
2891
  if (!empty($task)) {
2892
  extract($task['task_args']);
2893
  }
2894
+
2895
  $results = $task['task_results'];
2896
 
2897
  if (is_array($results) && count($results)) {
2901
  if ($backup_file && file_exists($backup_file)) {
2902
  //FTP, Amazon S3, Dropbox or Google Drive
2903
  if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
2904
+ $this->update_status($task_name, $this->statuses['ftp']);
2905
+ $account_info['mwp_ftp']['backup_file'] = $backup_file;
2906
  $return = $this->ftp_backup($account_info['mwp_ftp']);
2907
+ if (!(is_array($return) && isset($return['error']))) {
2908
+ $this->update_status($task_name, $this->statuses['ftp'], true);
2909
+ $this->update_status($task_name,$this->statuses['finished'], true);
2910
+ }
2911
  }
2912
 
2913
  if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
2914
+ $this->update_status($task_name, $this->statuses['s3']);
2915
+ $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
2916
  $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
2917
+ if (!(is_array($return) && isset($return['error']))) {
2918
+ $this->update_status($task_name, $this->statuses['s3'], true);
2919
+ $this->update_status($task_name,$this->statuses['finished'], true);
2920
+ }
2921
  }
2922
 
2923
  if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
2924
+ $this->update_status($task_name, $this->statuses['dropbox']);
2925
+ $account_info['mwp_dropbox']['backup_file'] = $backup_file;
2926
  $return = $this->dropbox_backup($account_info['mwp_dropbox']);
2927
+ if (!(is_array($return) && isset($return['error']))) {
2928
+ $this->update_status($task_name, $this->statuses['dropbox'], true);
2929
+ $this->update_status($task_name,$this->statuses['finished'], true);
2930
+ }
2931
  }
2932
 
2933
  if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
2934
+ $this->update_status($task_name, $this->statuses['email']);
2935
+ $account_info['mwp_email']['file_path'] = $backup_file;
2936
  $return = $this->email_backup($account_info['mwp_email']);
2937
+ if (!(is_array($return) && isset($return['error']))) {
2938
+ $this->update_status($task_name, $this->statuses['email'], true);
2939
+ $this->update_status($task_name,$this->statuses['finished'], true);
2940
+ }
2941
  }
2942
 
2943
  if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
2944
+ $this->update_status($task_name, $this->statuses['google_drive']);
2945
  $account_info['mwp_google_drive']['backup_file'] = $backup_file;
2946
  $return = $this->google_drive_backup($account_info['mwp_google_drive']);
2947
+ if (!(is_array($return) && isset($return['error']))) {
2948
+ $this->update_status($task_name, $this->statuses['google_drive'], true);
2949
+ $this->update_status($task_name,$this->statuses['finished'], true);
2950
+ }
2951
  }
2952
 
2953
+ $tasks = $this->tasks;
2954
  @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
2955
  if ($return == true && $del_host_file) {
2956
  @unlink($backup_file);
2957
+ unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
 
 
2958
  }
2959
+ $this->update_tasks($tasks);
 
 
2960
  } else {
2961
  $return = array(
2962
  'error' => 'Backup file not found on your server. Please try again.'
2964
  }
2965
 
2966
  return $return;
 
2967
  }
2968
 
2969
+ /**
2970
+ * Checks if scheduled backup tasks should be executed.
2971
+ *
2972
+ * @param array $args arguments passed to function
2973
+ * [task_name] -> name of backup task
2974
+ * [task_id] -> id of backup task
2975
+ * [$site_key] -> hash key of backup task
2976
+ * [worker_version] -> version of worker
2977
+ * [mwp_google_drive_refresh_token] -> should be Google Drive token be refreshed, true if it is remote destination of task
2978
+ * @param string $url url on master where worker validate task
2979
+ * @return string|array|boolean
2980
+ */
2981
+ function validate_task($args, $url) {
2982
  if (!class_exists('WP_Http')) {
2983
  include_once(ABSPATH . WPINC . '/class-http.php');
2984
  }
2985
+
2986
+ $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
2987
  $params = array('timeout'=>100);
2988
  $params['body'] = $args;
2989
  $result = wp_remote_post($url, $params);
 
 
 
 
 
 
 
 
 
 
 
 
2990
 
2991
+ if ($worker_upto_3_9_22) {
2992
+ if (is_array($result) && $result['body'] == 'mwp_delete_task') {
2993
+ //$tasks = $this->get_backup_settings();
2994
+ $tasks = $this->tasks;
2995
+ $this->update_tasks($tasks);
2996
+ $this->cleanup();
2997
+ exit;
2998
+ } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
2999
+ return 'paused';
3000
+ } elseif(is_array($result) && substr($result['body'], 0, 8) == 'token - '){
3001
+ return $result['body'];
3002
+ }
3003
+ } else {
3004
+ if (is_array($result) && $result['body']) {
3005
+ $response = unserialize($result['body']);
3006
+ if ($response['message'] == 'mwp_delete_task') {
3007
+ $tasks = $this->tasks;
3008
+ $this->update_tasks($tasks);
3009
+ $this->cleanup();
3010
+ exit;
3011
+ } elseif ($response['message'] == 'mwp_pause_task') {
3012
+ return 'paused';
3013
+ } elseif ($response['message'] == 'mwp_do_task') {
3014
+ return $response;
3015
+ }
3016
+ }
3017
+ }
3018
+
3019
+ return false;
3020
  }
3021
 
3022
+ /**
3023
+ * Updates status of backup task.
3024
+ * Positive number if completed, negative if not.
3025
+ *
3026
+ * @param string $task_name name of backup task
3027
+ * @param int $status status which tasks should be updated to
3028
+ * (
3029
+ * 0 - Backup started,
3030
+ * 1 - DB dump,
3031
+ * 2 - DB ZIP,
3032
+ * 3 - Files ZIP,
3033
+ * 4 - Amazon S3,
3034
+ * 5 - Dropbox,
3035
+ * 6 - FTP,
3036
+ * 7 - Email,
3037
+ * 8 - Google Drive,
3038
+ * 100 - Finished
3039
+ * )
3040
+ * @param bool $completed completed or not
3041
+ * @return void
3042
+ */
3043
+ function update_status($task_name, $status, $completed = false) {
 
 
 
 
 
 
 
3044
  if ($task_name != 'Backup Now') {
3045
  $tasks = $this->tasks;
3046
  $index = count($tasks[$task_name]['task_results']) - 1;
3059
  }
3060
  }
3061
 
3062
+ /**
3063
+ * Update $this->tasks attribute and save it to wp_options with key mwp_backup_tasks.
3064
+ *
3065
+ * @param mixed $tasks associative array with all tasks data
3066
+ * @return void
3067
+ */
3068
+ function update_tasks($tasks) {
3069
  $this->tasks = $tasks;
3070
  update_option('mwp_backup_tasks', $tasks);
3071
  }
3072
 
3073
+ /**
3074
+ * Reconnects to database to avoid timeout problem after ZIP files.
3075
+ *
3076
+ * @return void
3077
+ */
3078
+ function wpdb_reconnect() {
3079
  global $wpdb;
3080
+
3081
  if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
3082
  @mysql_close($wpdb->dbh);
3083
  $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
3085
  }
3086
  }
3087
 
3088
+ /**
3089
+ * Replaces .htaccess file in process of restoring WordPress site.
3090
+ *
3091
+ * @param string $url url of current site
3092
+ * @return void
3093
+ */
3094
+ function replace_htaccess($url) {
3095
+ $file = @file_get_contents(ABSPATH.'.htaccess');
3096
+ if ($file && strlen($file)) {
3097
+ $args = parse_url($url);
3098
+ $string = rtrim($args['path'], "/");
3099
+ $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
3100
+ $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
3101
+ $file = preg_replace($regex, $replace, $file);
3102
+ @file_put_contents(ABSPATH.'.htaccess', $file);
3103
+ }
3104
  }
3105
 
3106
+ /**
3107
+ * Removes cron for checking scheduled tasks, if there are not any scheduled task.
3108
+ *
3109
+ * @return void
3110
+ */
3111
+ function check_cron_remove() {
3112
  if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
3113
  wp_clear_scheduled_hook('mwp_backup_tasks');
3114
  exit;
3115
  }
3116
  }
3117
 
3118
+ /**
3119
+ * Readd tasks on new website add.
3120
+ *
3121
+ * @param array $params arguments passed to function
3122
+ * @return array $params without backups
3123
+ */
3124
+ public static function readd_tasks($params = array()) {
3125
  global $mmb_core;
3126
 
3127
  if( empty($params) || !isset($params['backups']) )
3168
  unset($params['backups']);
3169
  return $params;
3170
  }
3171
+
3172
+ /**
3173
+ * Upload to remote destination in the second step for scheduled backup run by cron.
3174
+ *
3175
+ * @param string $task_name name of backup task
3176
+ * @param string $backup_file absolute path of local backup archive
3177
+ * @param bool $del_host_file should be deleted local backup archive or not
3178
+ * @return void
3179
+ */
3180
+ function remote_upload($task_name, $backup_file, $del_host_file) {
3181
+ $this->set_memory();
3182
+
3183
+ $tasks = $this->tasks;
3184
+ $task = $tasks[$task_name];
3185
+
3186
+ if (!empty($task)) {
3187
+ extract($task['task_args']);
3188
+ }
3189
+
3190
+ if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
3191
+ $this->update_status($task_name, $this->statuses['ftp']);
3192
+ $account_info['mwp_ftp']['backup_file'] = $backup_file;
3193
+ $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
3194
+ if ($ftp_result !== true && $del_host_file) {
3195
+ @unlink($backup_file);
3196
+ }
3197
+ if (!(is_array($ftp_result) && isset($ftp_result['error']))) {
3198
+ $this->update_status($task_name, $this->statuses['ftp'], true);
3199
+ $this->update_status($task_name,$this->statuses['finished'], true);
3200
+ }
3201
+ }
3202
+
3203
+ if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
3204
+ $this->update_status($task_name, $this->statuses['s3']);
3205
+ $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
3206
+ $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
3207
+ if ($amazons3_result !== true && $del_host_file) {
3208
+ @unlink($backup_file);
3209
+ }
3210
+ if (!(is_array($amazons3_result) && isset($amazons3_result['error']))) {
3211
+ $this->update_status($task_name, $this->statuses['s3'], true);
3212
+ $this->update_status($task_name,$this->statuses['finished'], true);
3213
+ }
3214
+ }
3215
+
3216
+ if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
3217
+ $this->update_status($task_name, $this->statuses['dropbox']);
3218
+ $account_info['mwp_dropbox']['backup_file'] = $backup_file;
3219
+ $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
3220
+ if ($dropbox_result !== true && $del_host_file) {
3221
+ @unlink($backup_file);
3222
+ }
3223
+ if (!(is_array($dropbox_result) && isset($dropbox_result['error']))) {
3224
+ $this->update_status($task_name, $this->statuses['dropbox'], true);
3225
+ $this->update_status($task_name,$this->statuses['finished'], true);
3226
+ }
3227
+ }
3228
+
3229
+ if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
3230
+ $this->update_status($task_name, $this->statuses['email']);
3231
+ $account_info['mwp_email']['task_name'] = $task_name;
3232
+ $account_info['mwp_email']['file_path'] = $backup_file;
3233
+ $email_result = $this->email_backup($account_info['mwp_email']);
3234
+ if (!(is_array($email_result) && isset($email_result['error']))) {
3235
+ $this->update_status($task_name, $this->statuses['email'], true);
3236
+ $this->update_status($task_name,$this->statuses['finished'], true);
3237
+ }
3238
+ }
3239
+
3240
+ if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
3241
+ $this->update_status($task_name, $this->statuses['google_drive']);
3242
+ $account_info['mwp_google_drive']['backup_file'] = $backup_file;
3243
+ $google_drive_result = $this->google_drive_backup($account_info['mwp_google_drive']);
3244
+ if ($google_drive_result !== true && $del_host_file) {
3245
+ @unlink($backup_file);
3246
+ }
3247
+ if (!(is_array($google_drive_result) && isset($google_drive_result['error']))) {
3248
+ $this->update_status($task_name, $this->statuses['google_drive'], true);
3249
+ $this->update_status($task_name,$this->statuses['finished'], true);
3250
+ }
3251
+ }
3252
+
3253
+ $tasks = $this->tasks;
3254
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
3255
+ if ($del_host_file) {
3256
+ @unlink($backup_file);
3257
+ unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
3258
+ }
3259
+ $this->update_tasks($tasks);
3260
+ }
3261
+
3262
  }
3263
 
3264
+ if( function_exists('add_filter') ) {
3265
  add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
3266
  }
3267
+
3268
+ if(!function_exists('get_all_files_from_dir')) {
3269
+ /**
3270
+ * Get all files in directory
3271
+ *
3272
+ * @param string $path Relative or absolute path to folder
3273
+ * @param array $exclude List of excluded files or folders, relative to $path
3274
+ * @return array List of all files in folder $path, exclude all files in $exclude array
3275
+ */
3276
+ function get_all_files_from_dir($path, $exclude = array()) {
3277
+ if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
3278
+ global $directory_tree, $ignore_array;
3279
+ $directory_tree = array();
3280
+ foreach ($exclude as $file) {
3281
+ if (!in_array($file, array('.', '..'))) {
3282
+ if ($file[0] === "/") $path = substr($file, 1);
3283
+ $ignore_array[] = "$path/$file";
3284
+ }
3285
+ }
3286
+ get_all_files_from_dir_recursive($path);
3287
+ return $directory_tree;
3288
+ }
3289
+ }
3290
+
3291
+ if (!function_exists('get_all_files_from_dir_recursive')) {
3292
+ /**
3293
+ * Get all files in directory,
3294
+ * wrapped function which writes in global variable
3295
+ * and exclued files or folders are read from global variable
3296
+ *
3297
+ * @param string $path Relative or absolute path to folder
3298
+ * @return void
3299
+ */
3300
+ function get_all_files_from_dir_recursive($path) {
3301
+ if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
3302
+ global $directory_tree, $ignore_array;
3303
+ $directory_tree_temp = array();
3304
+ $dh = @opendir($path);
3305
+
3306
+ while (false !== ($file = @readdir($dh))) {
3307
+ if (!in_array($file, array('.', '..'))) {
3308
+ if (!in_array("$path/$file", $ignore_array)) {
3309
+ if (!is_dir("$path/$file")) {
3310
+ $directory_tree[] = "$path/$file";
3311
+ } else {
3312
+ get_all_files_from_dir_recursive("$path/$file");
3313
+ }
3314
+ }
3315
+ }
3316
+ }
3317
+ @closedir($dh);
3318
+ }
3319
+ }
3320
  ?>
core.class.php CHANGED
@@ -145,6 +145,7 @@ class MMB_Core extends MMB_Helper
145
 
146
  add_action('admin_init', array(&$this,'admin_actions'));
147
  add_action('init', array( &$this, 'mmb_remote_action'), 9999);
 
148
  add_action('setup_theme', 'mmb_parse_request');
149
  add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
150
  add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
145
 
146
  add_action('admin_init', array(&$this,'admin_actions'));
147
  add_action('init', array( &$this, 'mmb_remote_action'), 9999);
148
+ //add_action('setup_theme', 'mmb_run_backup_action', 1);
149
  add_action('setup_theme', 'mmb_parse_request');
150
  add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
151
  add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
helper.class.php CHANGED
@@ -350,13 +350,13 @@ class MMB_Helper
350
 
351
  if ((int) $current_message >= (int) $message_id)
352
  return array(
353
- 'error' => 'Invalid message recieved. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
354
  );
355
 
356
  $pl_key = $this->get_master_public_key();
357
  if (!$pl_key) {
358
  return array(
359
- 'error' => 'Authentication failed. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
360
  );
361
  }
362
 
@@ -367,7 +367,7 @@ class MMB_Helper
367
  return true;
368
  } else if ($verify == 0) {
369
  return array(
370
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
371
  );
372
  } else {
373
  return array(
@@ -380,13 +380,13 @@ class MMB_Helper
380
  return true;
381
  }
382
  return array(
383
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
384
  );
385
  }
386
  // no rand key - deleted in get_stat maybe
387
  else
388
  return array(
389
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
390
  );
391
  }
392
 
@@ -541,6 +541,22 @@ class MMB_Helper
541
  die('Error downloading file ' . $url);
542
  return $file_name;
543
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
 
545
  }
546
  ?>
350
 
351
  if ((int) $current_message >= (int) $message_id)
352
  return array(
353
+ 'error' => 'Invalid message recieved. Deactivate and activate the ManageWP Worker plugin on this site, then re-add it to your ManageWP account.'
354
  );
355
 
356
  $pl_key = $this->get_master_public_key();
357
  if (!$pl_key) {
358
  return array(
359
+ 'error' => 'Authentication failed. Deactivate and activate the ManageWP Worker plugin on this site, then re-add it to your ManageWP account.'
360
  );
361
  }
362
 
367
  return true;
368
  } else if ($verify == 0) {
369
  return array(
370
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then re-add it to your ManageWP account.'
371
  );
372
  } else {
373
  return array(
380
  return true;
381
  }
382
  return array(
383
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then re-add it to your ManageWP account.'
384
  );
385
  }
386
  // no rand key - deleted in get_stat maybe
387
  else
388
  return array(
389
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then re-add it to your ManageWP account.'
390
  );
391
  }
392
 
541
  die('Error downloading file ' . $url);
542
  return $file_name;
543
  }
544
+
545
+ function return_bytes($val) {
546
+ $val = trim($val);
547
+ $last = strtolower($val[strlen($val)-1]);
548
+ switch($last) {
549
+ // The 'G' modifier is available since PHP 5.1.0
550
+ case 'g':
551
+ $val *= 1024;
552
+ case 'm':
553
+ $val *= 1024;
554
+ case 'k':
555
+ $val *= 1024;
556
+ }
557
+
558
+ return $val;
559
+ }
560
 
561
  }
562
  ?>
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: ManageWP - Worker
4
  Plugin URI: http://managewp.com/
5
  Description: Manage all your blogs from one dashboard. Visit <a href="http://managewp.com">ManageWP.com</a> to sign up.
6
  Author: ManageWP
7
- Version: 3.9.22
8
  Author URI: http://managewp.com
9
  */
10
 
@@ -22,7 +22,7 @@ if(basename($_SERVER['SCRIPT_FILENAME']) == "init.php"):
22
  exit;
23
  endif;
24
  if(!defined('MMB_WORKER_VERSION'))
25
- define('MMB_WORKER_VERSION', '3.9.22');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
@@ -506,16 +506,21 @@ if( !function_exists ( 'mmb_run_task_now' )) {
506
  {
507
  global $mmb_core;
508
  $mmb_core->get_backup_instance();
509
- if (isset($params['google_drive_token'])) {
510
- $return = $mmb_core->backup_instance->task_now($params['task_name'], $params['google_drive_token']);
 
 
 
 
 
 
 
 
 
511
  } else {
512
- $return = $mmb_core->backup_instance->task_now($params['task_name']);
513
- }
514
- if (is_array($return) && array_key_exists('error', $return))
515
- mmb_response($return['error'], false);
516
- else {
517
- mmb_response($return, true);
518
  }
 
519
  }
520
  }
521
 
@@ -633,6 +638,20 @@ if( !function_exists ( 'mmb_clean_orphan_backups' )) {
633
  }
634
  }
635
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
636
  if( !function_exists ( 'mmb_update_worker_plugin' )) {
637
  function mmb_update_worker_plugin($params)
638
  {
@@ -1050,7 +1069,7 @@ if( !function_exists('mmb_more_reccurences') ){
1050
  }
1051
  }
1052
 
1053
- add_action('mwp_backup_tasks', 'mwp_check_backup_tasks');
1054
 
1055
  if( !function_exists('mwp_check_backup_tasks') ){
1056
  function mwp_check_backup_tasks() {
@@ -1062,6 +1081,23 @@ if( !function_exists('mwp_check_backup_tasks') ){
1062
  }
1063
  }
1064
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1065
  // if (!wp_next_scheduled('mwp_notifications')) {
1066
  // wp_schedule_event( time(), 'twicedaily', 'mwp_notifications' );
1067
  // }
@@ -1070,6 +1106,7 @@ if( !function_exists('mwp_check_backup_tasks') ){
1070
  if (!wp_next_scheduled('mwp_datasend')) {
1071
  wp_schedule_event( time(), 'threehours', 'mwp_datasend' );
1072
  }
 
1073
  add_action('mwp_datasend', 'mwp_datasend');
1074
 
1075
  if( !function_exists('mwp_check_notifications') ){
@@ -1212,4 +1249,4 @@ if( isset($_COOKIE[MMB_XFRAME_COOKIE]) ){
1212
  remove_action( 'login_init', 'send_frame_options_header');
1213
  }
1214
 
1215
- ?>
4
  Plugin URI: http://managewp.com/
5
  Description: Manage all your blogs from one dashboard. Visit <a href="http://managewp.com">ManageWP.com</a> to sign up.
6
  Author: ManageWP
7
+ Version: 3.9.23
8
  Author URI: http://managewp.com
9
  */
10
 
22
  exit;
23
  endif;
24
  if(!defined('MMB_WORKER_VERSION'))
25
+ define('MMB_WORKER_VERSION', '3.9.23');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
506
  {
507
  global $mmb_core;
508
  $mmb_core->get_backup_instance();
509
+
510
+ $task_name = isset($params['task_name']) ? $params['task_name'] : false;
511
+ $google_drive_token = isset($params['google_drive_token']) ? $params['google_drive_token'] : false;
512
+
513
+ if ($task_name) {
514
+ $return = $mmb_core->backup_instance->task_now($task_name, $google_drive_token);
515
+ if (is_array($return) && array_key_exists('error', $return))
516
+ mmb_response($return['error'], false);
517
+ else {
518
+ mmb_response($return, true);
519
+ }
520
  } else {
521
+ mmb_response("Task name is not provided.", false);
 
 
 
 
 
522
  }
523
+
524
  }
525
  }
526
 
638
  }
639
  }
640
 
641
+ /*function mmb_run_backup_action() {
642
+ if (!wp_verify_nonce($_POST['mmb_backup_nonce'], 'mmb-backup-nonce')) return false;
643
+ $args = @unserialize(stripslashes($_POST['args']));
644
+ if (!$args) return false;
645
+ $cron_action = isset($_POST['backup_cron_action']) ? $_POST['backup_cron_action'] : false;
646
+ if ($cron_action) {
647
+ do_action($cron_action, $args);
648
+ }
649
+ unset($_POST['mmb_backup_nonce']);
650
+ unset($_POST['args']);
651
+ unset($_POST['backup_cron_action']);
652
+ return true;
653
+ }*/
654
+
655
  if( !function_exists ( 'mmb_update_worker_plugin' )) {
656
  function mmb_update_worker_plugin($params)
657
  {
1069
  }
1070
  }
1071
 
1072
+ add_action('mwp_backup_tasks', 'mwp_check_backup_tasks');
1073
 
1074
  if( !function_exists('mwp_check_backup_tasks') ){
1075
  function mwp_check_backup_tasks() {
1081
  }
1082
  }
1083
 
1084
+ // Remote upload in the second request.
1085
+ add_action('mmb_scheduled_remote_upload', 'mmb_call_scheduled_remote_upload');
1086
+ //add_action('mmb_remote_upload', 'mmb_call_scheduled_remote_upload');
1087
+
1088
+ if( !function_exists('mmb_call_scheduled_remote_upload') ){
1089
+ function mmb_call_scheduled_remote_upload($args) {
1090
+ global $mmb_core, $_wp_using_ext_object_cache;
1091
+ $_wp_using_ext_object_cache = false;
1092
+ extract($args);
1093
+
1094
+ $mmb_core->get_backup_instance();
1095
+ if (isset($task_name) && isset($backup_file) && isset($del_host_file)) {
1096
+ $mmb_core->backup_instance->remote_upload($task_name, $backup_file, $del_host_file);
1097
+ }
1098
+ }
1099
+ }
1100
+
1101
  // if (!wp_next_scheduled('mwp_notifications')) {
1102
  // wp_schedule_event( time(), 'twicedaily', 'mwp_notifications' );
1103
  // }
1106
  if (!wp_next_scheduled('mwp_datasend')) {
1107
  wp_schedule_event( time(), 'threehours', 'mwp_datasend' );
1108
  }
1109
+
1110
  add_action('mwp_datasend', 'mwp_datasend');
1111
 
1112
  if( !function_exists('mwp_check_notifications') ){
1249
  remove_action( 'login_init', 'send_frame_options_header');
1250
  }
1251
 
1252
+ ?>
installer.class.php CHANGED
@@ -101,18 +101,31 @@ class MMB_Installer extends MMB_Core
101
 
102
  $wp_themes = null;
103
  unset($wp_themes); //prevent theme data caching
104
-
105
- $all_themes = get_themes();
106
- foreach ($all_themes as $theme_name => $theme_data) {
107
- foreach ($install_info as $key => $install) {
108
- if (!$install || is_wp_error($install))
109
- continue;
110
-
111
- if ($theme_data['Template'] == $install['destination_name']) {
112
- $install_info[$key]['activated'] = switch_theme($theme_data['Template'], $theme_data['Stylesheet']);
113
- }
114
- }
115
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
  }
118
  ob_clean();
@@ -622,31 +635,60 @@ class MMB_Installer extends MMB_Core
622
 
623
  function get_upgradable_themes( $filter = array() )
624
  {
625
- $all_themes = get_themes();
626
- $upgrade_themes = array();
627
-
628
- $current = $this->mmb_get_transient('update_themes');
629
- if (!empty($current->response)) {
630
- foreach ((array) $all_themes as $theme_template => $theme_data) {
631
- if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
632
- continue;
633
-
634
- if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
635
- continue;
636
 
637
- foreach ($current->response as $current_themes => $theme) {
638
- if ($theme_data['Template'] == $current_themes) {
639
- if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
640
- $current->response[$current_themes]['name'] = $theme_data['Name'];
641
- $current->response[$current_themes]['old_version'] = $theme_data['Version'];
642
- $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
643
- $upgrade_themes[] = $current->response[$current_themes];
644
- }
645
- }
646
- }
647
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  }
649
 
 
650
  return $upgrade_themes;
651
  }
652
 
@@ -734,53 +776,101 @@ class MMB_Installer extends MMB_Core
734
 
735
  extract($args);
736
 
737
- if (!function_exists('get_themes')) {
738
  include_once(ABSPATH . WPINC . '/theme.php');
739
  }
740
- $all_themes = get_themes();
741
- $themes = array(
742
- 'active' => array(),
743
- 'inactive' => array()
744
- );
745
-
746
- if (is_array($all_themes) && !empty($all_themes)) {
747
- $current_theme = get_current_theme();
748
-
749
- $br_a = 0;
750
- $br_i = 0;
751
- foreach ($all_themes as $theme_name => $theme) {
752
- if ($current_theme == $theme_name) {
753
- $themes['active'][$br_a]['path'] = $theme['Template'];
754
- $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
755
- $themes['active'][$br_a]['version'] = $theme['Version'];
756
- $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
757
- $br_a++;
758
- }
759
-
760
- if ($current_theme != $theme_name) {
761
- $themes['inactive'][$br_i]['path'] = $theme['Template'];
762
- $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
763
- $themes['inactive'][$br_i]['version'] = $theme['Version'];
764
- $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
765
- $br_i++;
766
- }
767
-
768
- }
769
-
770
- if ($search) {
771
- foreach ($themes['active'] as $k => $theme) {
772
- if (!stristr($theme['name'], $search)) {
773
- unset($themes['active'][$k]);
774
- }
775
- }
776
-
777
- foreach ($themes['inactive'] as $k => $theme) {
778
- if (!stristr($theme['name'], $search)) {
779
- unset($themes['inactive'][$k]);
780
- }
781
- }
782
- }
783
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
 
785
  return $themes;
786
  }
101
 
102
  $wp_themes = null;
103
  unset($wp_themes); //prevent theme data caching
104
+ if(function_exists('wp_get_themes')){
105
+ $all_themes = wp_get_themes();
106
+ foreach ($all_themes as $theme_name => $theme_data) {
107
+ foreach ($install_info as $key => $install) {
108
+ if (!$install || is_wp_error($install))
109
+ continue;
110
+
111
+ if ($theme_data->Template == $install['destination_name']) {
112
+ $install_info[$key]['activated'] = switch_theme($theme_data->Template, $theme_data->Stylesheet);
113
+ }
114
+ }
115
+ }
116
+ }else{
117
+ $all_themes = get_themes();
118
+ foreach ($all_themes as $theme_name => $theme_data) {
119
+ foreach ($install_info as $key => $install) {
120
+ if (!$install || is_wp_error($install))
121
+ continue;
122
+
123
+ if ($theme_data['Template'] == $install['destination_name']) {
124
+ $install_info[$key]['activated'] = switch_theme($theme_data['Template'], $theme_data['Stylesheet']);
125
+ }
126
+ }
127
+ }
128
+ }
129
  }
130
  }
131
  ob_clean();
635
 
636
  function get_upgradable_themes( $filter = array() )
637
  {
638
+ if(function_exists('wp_get_themes')){
639
+ $all_themes = wp_get_themes();
640
+ $upgrade_themes = array();
641
+
642
+ $current = $this->mmb_get_transient('update_themes');
643
+ if (!empty($current->response)) {
644
+ foreach ((array) $all_themes as $theme_template => $theme_data) {
645
+ if(isset($theme_data->{'Parent Theme'}) && !empty($theme_data->{'Parent Theme'}))
646
+ continue;
 
 
647
 
648
+ if(isset($theme_data->Name) && in_array($theme_data->Name, $filter))
649
+ continue;
650
+
651
+ foreach ($current->response as $current_themes => $theme) {
652
+ if ($theme_data->Template == $current_themes) {
653
+ if (strlen($theme_data->Name) > 0 && strlen($theme_data->Version) > 0) {
654
+ $current->response[$current_themes]['name'] = $theme_data->Name;
655
+ $current->response[$current_themes]['old_version'] = $theme_data->Version;
656
+ $current->response[$current_themes]['theme_tmp'] = $theme_data->Template;
657
+ $upgrade_themes[] = $current->response[$current_themes];
658
+ }
659
+ }
660
+ }
661
+ }
662
+ }
663
+ }else{
664
+ $all_themes = get_themes();
665
+
666
+ $upgrade_themes = array();
667
+
668
+ $current = $this->mmb_get_transient('update_themes');
669
+ if (!empty($current->response)) {
670
+ foreach ((array) $all_themes as $theme_template => $theme_data) {
671
+ if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
672
+ continue;
673
+
674
+ if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
675
+ continue;
676
+
677
+ foreach ($current->response as $current_themes => $theme) {
678
+ if ($theme_data['Template'] == $current_themes) {
679
+ if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
680
+ $current->response[$current_themes]['name'] = $theme_data['Name'];
681
+ $current->response[$current_themes]['old_version'] = $theme_data['Version'];
682
+ $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
683
+ $upgrade_themes[] = $current->response[$current_themes];
684
+ }
685
+ }
686
+ }
687
+ }
688
+ }
689
  }
690
 
691
+
692
  return $upgrade_themes;
693
  }
694
 
776
 
777
  extract($args);
778
 
779
+ if (!function_exists('wp_get_themes')) {
780
  include_once(ABSPATH . WPINC . '/theme.php');
781
  }
782
+ if(function_exists('wp_get_themes')){
783
+ $all_themes = wp_get_themes();
784
+ $themes = array(
785
+ 'active' => array(),
786
+ 'inactive' => array()
787
+ );
788
+
789
+ if (is_array($all_themes) && !empty($all_themes)) {
790
+ $current_theme = get_current_theme();
791
+
792
+ $br_a = 0;
793
+ $br_i = 0;
794
+ foreach ($all_themes as $theme_name => $theme) {
795
+ if ($current_theme == strip_tags($theme->Name)) {
796
+ $themes['active'][$br_a]['path'] = $theme->Template;
797
+ $themes['active'][$br_a]['name'] = strip_tags($theme->Name);
798
+ $themes['active'][$br_a]['version'] = $theme->Version;
799
+ $themes['active'][$br_a]['stylesheet'] = $theme->Stylesheet;
800
+ $br_a++;
801
+ }
802
+
803
+ if ($current_theme != strip_tags($theme->Name)) {
804
+ $themes['inactive'][$br_i]['path'] = $theme->Template;
805
+ $themes['inactive'][$br_i]['name'] = strip_tags($theme->Name);
806
+ $themes['inactive'][$br_i]['version'] = $theme->Version;
807
+ $themes['inactive'][$br_i]['stylesheet'] = $theme->Stylesheet;
808
+ $br_i++;
809
+ }
810
+
811
+ }
812
+
813
+ if ($search) {
814
+ foreach ($themes['active'] as $k => $theme) {
815
+ if (!stristr($theme['name'], $search)) {
816
+ unset($themes['active'][$k]);
817
+ }
818
+ }
819
+
820
+ foreach ($themes['inactive'] as $k => $theme) {
821
+ if (!stristr($theme['name'], $search)) {
822
+ unset($themes['inactive'][$k]);
823
+ }
824
+ }
825
+ }
826
+ }
827
+ }else{
828
+ $all_themes = get_themes();
829
+ $themes = array(
830
+ 'active' => array(),
831
+ 'inactive' => array()
832
+ );
833
+
834
+ if (is_array($all_themes) && !empty($all_themes)) {
835
+ $current_theme = get_current_theme();
836
+
837
+ $br_a = 0;
838
+ $br_i = 0;
839
+ foreach ($all_themes as $theme_name => $theme) {
840
+ if ($current_theme == $theme_name) {
841
+ $themes['active'][$br_a]['path'] = $theme['Template'];
842
+ $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
843
+ $themes['active'][$br_a]['version'] = $theme['Version'];
844
+ $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
845
+ $br_a++;
846
+ }
847
+
848
+ if ($current_theme != $theme_name) {
849
+ $themes['inactive'][$br_i]['path'] = $theme['Template'];
850
+ $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
851
+ $themes['inactive'][$br_i]['version'] = $theme['Version'];
852
+ $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
853
+ $br_i++;
854
+ }
855
+
856
+ }
857
+
858
+ if ($search) {
859
+ foreach ($themes['active'] as $k => $theme) {
860
+ if (!stristr($theme['name'], $search)) {
861
+ unset($themes['active'][$k]);
862
+ }
863
+ }
864
+
865
+ foreach ($themes['inactive'] as $k => $theme) {
866
+ if (!stristr($theme['name'], $search)) {
867
+ unset($themes['inactive'][$k]);
868
+ }
869
+ }
870
+ }
871
+ }
872
+
873
+ }
874
 
875
  return $themes;
876
  }
lib/dropbox.oauth.php DELETED
@@ -1,1134 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Dropbox class
5
- *
6
- * This source file can be used to communicate with Dropbox (http://dropbox.com)
7
- *
8
- * The class is documented in the file itself. If you find any bugs help me out and report them. Reporting can be done by sending an email to php-dropbox-bugs[at]verkoyen[dot]eu.
9
- * If you report a bug, make sure you give me enough information (include your code).
10
- *
11
- * Changelog since 1.0.4
12
- * - Fixed filesPost so it returns a boolean.
13
- * - Some code styling
14
- *
15
- * Changelog since 1.0.3
16
- * - Corrected the authorize-URL (thx to Jacob Budin).
17
- *
18
- * Changelog since 1.0.2
19
- * - Added methods to enable oauth-usage.
20
- *
21
- * Changelog since 1.0.1
22
- * - Bugfix: when doing multiple calles where GET and POST is mixed, the postfields should be reset (thx to Daniel Hトてスsken)
23
- *
24
- * Changelog since 1.0.0
25
- * - fixed some issues with generation off the basestring
26
- *
27
- * License
28
- * Copyright (c), Tijs Verkoyen. All rights reserved.
29
- *
30
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
31
- *
32
- * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
33
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
34
- * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
35
- *
36
- * This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
37
- *
38
- * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
39
- * @version 1.0.5
40
- *
41
- * @copyright Copyright (c), Tijs Verkoyen. All rights reserved.
42
- * @license BSD License
43
- */
44
- class Dropbox
45
- {
46
- // internal constant to enable/disable debugging
47
- const DEBUG = false;
48
-
49
- // url for the dropbox-api
50
- const API_URL = 'https://api.dropbox.com';
51
- const API_AUTH_URL = 'https://www.dropbox.com';
52
- const API_CONTENT_URL = 'https://api-content.dropbox.com';
53
-
54
- // port for the dropbox-api
55
- const API_PORT = 443;
56
-
57
- // current version
58
- const VERSION = '1.0.5';
59
-
60
-
61
- /**
62
- * A cURL instance
63
- *
64
- * @var resource
65
- */
66
- private $curl;
67
-
68
-
69
- /**
70
- * The application key
71
- *
72
- * @var string
73
- */
74
- private $applicationKey;
75
-
76
-
77
- /**
78
- * The application secret
79
- *
80
- * @var string
81
- */
82
- private $applicationSecret;
83
-
84
-
85
- /**
86
- * The oAuth-token
87
- *
88
- * @var string
89
- */
90
- private $oAuthToken = '';
91
-
92
-
93
- /**
94
- * The oAuth-token-secret
95
- *
96
- * @var string
97
- */
98
- private $oAuthTokenSecret = '';
99
-
100
-
101
- /**
102
- * The timeout
103
- *
104
- * @var int
105
- */
106
- private $timeOut = 60;
107
-
108
-
109
- /**
110
- * The user agent
111
- *
112
- * @var string
113
- */
114
- private $userAgent;
115
-
116
-
117
- // class methods
118
- /**
119
- * Default constructor
120
- *
121
- * @return void
122
- * @param string $applicationKey The application key to use.
123
- * @param string $applicationSecret The application secret to use.
124
- */
125
- public function __construct($applicationKey, $applicationSecret)
126
- {
127
- $this->setApplicationKey($applicationKey);
128
- $this->setApplicationSecret($applicationSecret);
129
- }
130
-
131
-
132
- /**
133
- * Default destructor
134
- *
135
- * @return void
136
- */
137
- public function __destruct()
138
- {
139
- if($this->curl != null) curl_close($this->curl);
140
- }
141
-
142
-
143
- /**
144
- * Format the parameters as a querystring
145
- *
146
- * @return string
147
- * @param array $parameters The parameters to pass.
148
- */
149
- private function buildQuery(array $parameters)
150
- {
151
- // no parameters?
152
- if(empty($parameters)) return '';
153
-
154
- // encode the keys
155
- $keys = self::urlencode_rfc3986(array_keys($parameters));
156
-
157
- // encode the values
158
- $values = self::urlencode_rfc3986(array_values($parameters));
159
-
160
- // reset the parameters
161
- $parameters = array_combine($keys, $values);
162
-
163
- // sort parameters by key
164
- uksort($parameters, 'strcmp');
165
-
166
- // loop parameters
167
- foreach($parameters as $key => $value)
168
- {
169
- // sort by value
170
- if(is_array($value)) $parameters[$key] = natsort($value);
171
- }
172
-
173
- // process parameters
174
- foreach($parameters as $key => $value) $chunks[] = $key . '=' . str_replace('%25', '%', $value);
175
-
176
- // return
177
- return implode('&', $chunks);
178
- }
179
-
180
-
181
- /**
182
- * All OAuth 1.0 requests use the same basic algorithm for creating a signature base string and a signature.
183
- * The signature base string is composed of the HTTP method being used, followed by an ampersand ("&") and then the URL-encoded base URL being accessed,
184
- * complete with path (but not query parameters), followed by an ampersand ("&").
185
- * Then, you take all query parameters and POST body parameters (when the POST body is of the URL-encoded type, otherwise the POST body is ignored),
186
- * including the OAuth parameters necessary for negotiation with the request at hand, and sort them in lexicographical order by first parameter name and
187
- * then parameter value (for duplicate parameters), all the while ensuring that both the key and the value for each parameter are URL encoded in isolation.
188
- * Instead of using the equals ("=") sign to mark the key/value relationship, you use the URL-encoded form of "%3D". Each parameter is then joined by the
189
- * URL-escaped ampersand sign, "%26".
190
- *
191
- * @return string
192
- * @param string $url The url to use.
193
- * @param string $method The method that will be called.
194
- * @param array $parameters The parameters to pass.
195
- */
196
- private function calculateBaseString($url, $method, array $parameters)
197
- {
198
- // redefine
199
- $url = (string) $url;
200
- $parameters = (array) $parameters;
201
-
202
- // init var
203
- $pairs = array();
204
- $chunks = array();
205
-
206
- // sort parameters by key
207
- uksort($parameters, 'strcmp');
208
-
209
- // loop parameters
210
- foreach($parameters as $key => $value)
211
- {
212
- // sort by value
213
- if(is_array($value)) $parameters[$key] = natsort($value);
214
- }
215
-
216
- // process queries
217
- foreach($parameters as $key => $value)
218
- {
219
- // only add if not already in the url
220
- if(substr_count($url, $key . '=' . $value) == 0) $chunks[] = self::urlencode_rfc3986($key) . '%3D' . self::urlencode_rfc3986($value);
221
- }
222
-
223
- $urlChunks = explode('/', $url);
224
- $i = 0;
225
-
226
- foreach($urlChunks as &$chunk)
227
- {
228
- if($i > 4) $chunk = self::urlencode_rfc3986($chunk);
229
- else $chunk = urlencode($chunk);
230
-
231
- $i++;
232
-
233
- }
234
-
235
- // build base
236
- $base = $method . '&';
237
- $base .= implode('%2F', $urlChunks);
238
- $base .= (substr_count($url, '?')) ? '%26' : '&';
239
- $base .= implode('%26', $chunks);
240
- $base = str_replace(array('%3F', '%20'), array('&', '%2520'), $base);
241
-
242
- // return
243
- return $base;
244
- }
245
-
246
-
247
- /**
248
- * Build the Authorization header
249
- * @later: fix me
250
- *
251
- * @return string
252
- * @param array $parameters The parameters to pass.
253
- * @param string $url The url to use.
254
- */
255
- private function calculateHeader(array $parameters, $url)
256
- {
257
- // redefine
258
- $url = (string) $url;
259
-
260
- // divide into parts
261
- $parts = parse_url($url);
262
-
263
- // init var
264
- $chunks = array();
265
-
266
- // process queries
267
- foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', self::urlencode_rfc3986($key) . '="' . self::urlencode_rfc3986($value) . '"');
268
- $parts['path']=str_replace("%2F", "/", rawurlencode($parts['path']));
269
- // build return
270
- $return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
271
- $return .= implode(',', $chunks);
272
- // prepend name and OAuth part
273
- return $return;
274
- }
275
-
276
-
277
- /**
278
- * Make an call to the oAuth
279
- * @todo refactor me
280
- *
281
- * @return array
282
- * @param string $url The url that has to be called.
283
- * @param array[optional] $parameters The parameters to pass.
284
- * @param string[optional] $method Which HTTP-method should we use? Possible values are POST, GET.
285
- * @param bool[optional] $expectJSON Do we expect JSON?
286
- */
287
- private function doOAuthCall($url, array $parameters = null, $method = 'POST', $expectJSON = true)
288
- {
289
- // redefine
290
- $url = (string) $url;
291
-
292
- // append default parameters
293
- $parameters['oauth_consumer_key'] = $this->getApplicationKey();
294
- $parameters['oauth_nonce'] = md5(microtime() . rand());
295
- $parameters['oauth_timestamp'] = time();
296
- $parameters['oauth_signature_method'] = 'HMAC-SHA1';
297
- $parameters['oauth_version'] = '1.0';
298
-
299
- // calculate the base string
300
- $base = $this->calculateBaseString(self::API_URL . '/' . $url, 'POST', $parameters);
301
-
302
- // add sign into the parameters
303
- $parameters['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
304
-
305
- // calculate header
306
- $header = $this->calculateHeader($parameters, self::API_URL . '/' . $url);
307
-
308
- if($method == 'POST')
309
- {
310
- $options[CURLOPT_POST] = true;
311
- $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
312
- }
313
-
314
- else
315
- {
316
- // reset post
317
- $options[CURLOPT_POST] = 0;
318
- unset($options[CURLOPT_POSTFIELDS]);
319
-
320
- // add the parameters into the querystring
321
- if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
322
- }
323
-
324
- // set options
325
- $options[CURLOPT_URL] = self::API_URL . '/' . $url;
326
- $options[CURLOPT_PORT] = self::API_PORT;
327
- $options[CURLOPT_USERAGENT] = $this->getUserAgent();
328
- if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
329
- $options[CURLOPT_RETURNTRANSFER] = true;
330
- $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
331
- $options[CURLOPT_SSL_VERIFYPEER] = false;
332
- $options[CURLOPT_SSL_VERIFYHOST] = false;
333
- $options[CURLOPT_HTTPHEADER] = array('Expect:');
334
-
335
- // init
336
- $this->curl = curl_init();
337
-
338
- // set options
339
- curl_setopt_array($this->curl, $options);
340
-
341
- // execute
342
- $response = curl_exec($this->curl);
343
- $headers = curl_getinfo($this->curl);
344
-
345
- // fetch errors
346
- $errorNumber = curl_errno($this->curl);
347
- $errorMessage = curl_error($this->curl);
348
-
349
- // error?
350
- if($errorNumber != '') throw new DropboxException($errorMessage, $errorNumber);
351
-
352
- // return
353
- if($expectJSON) return json_decode($response, true);
354
-
355
- // fallback
356
- return $response;
357
- }
358
-
359
-
360
- /**
361
- * Make the call
362
- *
363
- * @return string
364
- * @param string $url The url to call.
365
- * @param array[optional] $parameters Optional parameters.
366
- * @param bool[optional] $method The method to use. Possible values are GET, POST.
367
- * @param string[optional] $filePath The path to the file to upload.
368
- * @param bool[optional] $expectJSON Do we expect JSON?
369
- * @param bool[optional] $isContent Is this content?
370
- */
371
- private function doCall($url, array $parameters = null, $method = 'GET', $filePath = null, $expectJSON = true, $isContent = false)
372
- {
373
- // allowed methods
374
- $allowedMethods = array('GET', 'POST');
375
-
376
- // redefine
377
- $url = (string) $url;
378
- $parameters = (array) $parameters;
379
- $method = (string) $method;
380
- $expectJSON = (bool) $expectJSON;
381
-
382
- // validate method
383
- if(!in_array($method, $allowedMethods)) throw new DropboxException('Unknown method (' . $method . '). Allowed methods are: ' . implode(', ', $allowedMethods));
384
-
385
- // append default parameters
386
- $oauth['oauth_consumer_key'] = $this->getApplicationKey();
387
- $oauth['oauth_nonce'] = md5(microtime() . rand());
388
- $oauth['oauth_timestamp'] = time();
389
- $oauth['oauth_token'] = $this->getOAuthToken();
390
- $oauth['oauth_signature_method'] = 'HMAC-SHA1';
391
- $oauth['oauth_version'] = '1.0';
392
-
393
- // set data
394
- $data = $oauth;
395
- if(!empty($parameters))
396
- {
397
- // convert to UTF-8
398
- foreach($parameters as &$value) $value = utf8_encode($value);
399
-
400
- // merge
401
- $data = array_merge($data, $parameters);
402
- }
403
-
404
- if($filePath != null)
405
- {
406
- // process file
407
- $fileInfo = pathinfo($filePath);
408
-
409
- // add to the data
410
- $data['file'] = $fileInfo['basename'];
411
-
412
- }
413
-
414
- // calculate the base string
415
- if($isContent) $base = $this->calculateBaseString(self::API_CONTENT_URL . '/' . $url, $method, $data);
416
- else $base = $this->calculateBaseString(self::API_URL . '/' . $url, $method, $data);
417
-
418
- // based on the method, we should handle the parameters in a different way
419
- if($method == 'POST')
420
- {
421
- // file provided?
422
- if($filePath != null)
423
- {
424
- // build a boundary
425
- $boundary = md5(time());
426
-
427
- // init var
428
- $content = '--' . $boundary . "\r\n";
429
-
430
- // set file
431
- $content .= 'Content-Disposition: form-data; name=file; filename="' . $fileInfo['basename'] . '"' . "\r\n";
432
- $content .= 'Content-Type: application/octet-stream' . "\r\n";
433
- $content .= "\r\n";
434
- $content .= file_get_contents($filePath);
435
- $content .= "\r\n";
436
- $content .= "--" . $boundary . '--';
437
-
438
- // build headers
439
- $headers[] = 'Content-Type: multipart/form-data; boundary=' . $boundary;
440
- $headers[] = 'Content-Length: ' . strlen($content);
441
-
442
- // set content
443
- $options[CURLOPT_POSTFIELDS] = $content;
444
- }
445
-
446
- // no file
447
- else $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
448
-
449
- // enable post
450
- $options[CURLOPT_POST] = 1;
451
- }
452
-
453
- else
454
- {
455
- // reset post
456
- $options[CURLOPT_POST] = 0;
457
- unset($options[CURLOPT_POSTFIELDS]);
458
- $url=str_replace("%2F", "/", rawurlencode($url));
459
-
460
- // add the parameters into the querystring
461
- if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
462
- }
463
-
464
- // add sign into the parameters
465
- $oauth['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
466
-
467
- if($isContent) $headers[] = $this->calculateHeader($oauth, self::API_CONTENT_URL . '/' . $url);
468
- else $headers[] = $this->calculateHeader($oauth, self::API_URL . '/' . $url);
469
- $headers[] = 'Expect:';
470
-
471
- // set options
472
- if($isContent) $options[CURLOPT_URL] = self::API_CONTENT_URL . '/' . $url;
473
- else $options[CURLOPT_URL] = self::API_URL . '/' . $url;
474
- $options[CURLOPT_PORT] = self::API_PORT;
475
- $options[CURLOPT_USERAGENT] = $this->getUserAgent();
476
- if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
477
- $options[CURLOPT_RETURNTRANSFER] = true;
478
- $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
479
- $options[CURLOPT_SSL_VERIFYPEER] = false;
480
- $options[CURLOPT_SSL_VERIFYHOST] = false;
481
- $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
482
- $options[CURLOPT_HTTPHEADER] = $headers;
483
- // init
484
- if($this->curl == null) $this->curl = curl_init();
485
-
486
- // set options
487
- curl_setopt_array($this->curl, $options);
488
-
489
- // execute
490
- $response = curl_exec($this->curl);
491
- $headers = curl_getinfo($this->curl);
492
-
493
- // fetch errors
494
- $errorNumber = curl_errno($this->curl);
495
- $errorMessage = curl_error($this->curl);
496
-
497
- if(!$expectJSON && $isContent)
498
- {
499
- // is it JSON?
500
- $json = @json_decode($response, true);
501
- if($json !== false && isset($json['error'])) throw new DropboxException($json['error']);
502
-
503
- // set return
504
- $return['content_type'] = $headers['content_type'];
505
- $return['data'] = base64_encode($response);
506
-
507
- // return
508
- return $return;
509
- }
510
-
511
- // we don't expect JSON, return the response
512
- if(!$expectJSON) return $response;
513
-
514
- // replace ids with their string values, added because of some PHP-version can't handle these large values
515
- $response = preg_replace('/id":(\d+)/', 'id":"\1"', $response);
516
-
517
- // we expect JSON, so decode it
518
- $json = @json_decode($response, true);
519
-
520
- // validate JSON
521
- if($json === null)
522
- {
523
- // should we provide debug information
524
- if(self::DEBUG)
525
- {
526
- // make it output proper
527
- echo '<pre>';
528
-
529
- // dump the header-information
530
- var_dump($headers);
531
-
532
- // dump the error
533
- var_dump($errorMessage);
534
-
535
- // dump the raw response
536
- var_dump($response);
537
-
538
- // end proper format
539
- echo '</pre>';
540
- }
541
-
542
- // throw exception
543
- throw new DropboxException('Invalid response.');
544
- }
545
-
546
- // any error
547
- if(isset($json['error']))
548
- {
549
- // should we provide debug information
550
- if(self::DEBUG)
551
- {
552
- // make it output proper
553
- echo '<pre>';
554
-
555
- // dump the header-information
556
- var_dump($headers);
557
-
558
- // dump the raw response
559
- var_dump($response);
560
-
561
- // end proper format
562
- echo '</pre>';
563
- }
564
-
565
- if(isset($json['error']) && is_string($json['error'])) $message = $json['error'];
566
- elseif(isset($json['error']['hash']) && $json['error']['hash'] != '') $message = (string) $json['error']['hash'];
567
- else $message = 'Invalid response.';
568
-
569
- // throw exception
570
- throw new DropboxException($message);
571
- }
572
-
573
- // return
574
- return $json;
575
- }
576
-
577
-
578
- /**
579
- * Get the application key
580
- *
581
- * @return string
582
- */
583
- private function getApplicationKey()
584
- {
585
- return $this->applicationKey;
586
- }
587
-
588
-
589
- /**
590
- * Get the application secret
591
- *
592
- * @return string
593
- */
594
- private function getApplicationSecret()
595
- {
596
- return $this->applicationSecret;
597
- }
598
-
599
-
600
- /**
601
- * Get the oAuth-token
602
- *
603
- * @return string
604
- */
605
- private function getOAuthToken()
606
- {
607
- return $this->oAuthToken;
608
- }
609
-
610
-
611
- /**
612
- * Get the oAuth-token-secret
613
- *
614
- * @return string
615
- */
616
- private function getOAuthTokenSecret()
617
- {
618
- return $this->oAuthTokenSecret;
619
- }
620
-
621
-
622
- /**
623
- * Get the timeout
624
- *
625
- * @return int
626
- */
627
- public function getTimeOut()
628
- {
629
- return (int) $this->timeOut;
630
- }
631
-
632
-
633
- /**
634
- * Get the useragent that will be used. Our version will be prepended to yours.
635
- * It will look like: "PHP Dropbox/<version> <your-user-agent>"
636
- *
637
- * @return string
638
- */
639
- public function getUserAgent()
640
- {
641
- return (string) 'PHP Dropbox/' . self::VERSION . ' ' . $this->userAgent;
642
- }
643
-
644
-
645
- /**
646
- * Set the application key
647
- *
648
- * @return void
649
- * @param string $key The application key to use.
650
- */
651
- private function setApplicationKey($key)
652
- {
653
- $this->applicationKey = (string) $key;
654
- }
655
-
656
-
657
- /**
658
- * Set the application secret
659
- *
660
- * @return void
661
- * @param string $secret The application secret to use.
662
- */
663
- private function setApplicationSecret($secret)
664
- {
665
- $this->applicationSecret = (string) $secret;
666
- }
667
-
668
-
669
- /**
670
- * Set the oAuth-token
671
- *
672
- * @return void
673
- * @param string $token The token to use.
674
- */
675
- public function setOAuthToken($token)
676
- {
677
- $this->oAuthToken = (string) $token;
678
- }
679
-
680
-
681
- /**
682
- * Set the oAuth-secret
683
- *
684
- * @return void
685
- * @param string $secret The secret to use.
686
- */
687
- public function setOAuthTokenSecret($secret)
688
- {
689
- $this->oAuthTokenSecret = (string) $secret;
690
- }
691
-
692
-
693
- /**
694
- * Set the timeout
695
- *
696
- * @return void
697
- * @param int $seconds The timeout in seconds.
698
- */
699
- public function setTimeOut($seconds)
700
- {
701
- $this->timeOut = (int) $seconds;
702
- }
703
-
704
-
705
- /**
706
- * Get the useragent that will be used. Our version will be prepended to yours.
707
- * It will look like: "PHP Dropbox/<version> <your-user-agent>"
708
- *
709
- * @return void
710
- * @param string $userAgent Your user-agent, it should look like <app-name>/<app-version>.
711
- */
712
- public function setUserAgent($userAgent)
713
- {
714
- $this->userAgent = (string) $userAgent;
715
- }
716
-
717
-
718
- /**
719
- * Build the signature for the data
720
- *
721
- * @return string
722
- * @param string $key The key to use for signing.
723
- * @param string $data The data that has to be signed.
724
- */
725
- private function hmacsha1($key, $data)
726
- {
727
- return base64_encode(hash_hmac('SHA1', $data, $key, true));
728
- }
729
-
730
-
731
- /**
732
- * URL-encode method for internatl use
733
- *
734
- * @return string
735
- * @param mixed $value The value to encode.
736
- */
737
- private static function urlencode_rfc3986($value)
738
- {
739
- if(is_array($value)) return array_map(array('Dropbox', 'urlencode_rfc3986'), $value);
740
- else
741
- {
742
- $search = array('+', ' ', '%7E', '%');
743
- $replace = array('%20', '%20', '~', '%25');
744
-
745
- return str_replace($search, $replace, rawurlencode($value));
746
- }
747
- }
748
-
749
-
750
- // oauth resources
751
- /**
752
- * Call for obtaining an OAuth request token.
753
- * Returns a request token and the corresponding request token secret. This token and secret cannot be used to sign requests for the /metadata and /file content API calls.
754
- * Their only purpose is for signing a request to oauth/access_token once the user has gone through the application authorization steps provided by oauth/authorize.
755
- *
756
- * @return array
757
- */
758
- public function oAuthRequestToken()
759
- {
760
- // make the call
761
- $response = $this->doOAuthCall('1/oauth/request_token', null, 'POST', false);
762
-
763
- // process response
764
- $response = (array) explode('&', $response);
765
- $return = array();
766
-
767
- // loop chunks
768
- foreach($response as $chunk)
769
- {
770
- // split again
771
- $chunks = explode('=', $chunk, 2);
772
-
773
- // store return
774
- if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
775
- }
776
-
777
- // return
778
- return $return;
779
- }
780
-
781
-
782
- /**
783
- * Redirect the user to the oauth/authorize location so that Dropbox can authenticate the user and ask whether or not the user wants to authorize the application to access
784
- * file metadata and content on its behalf. oauth/authorize is not an API call per se, because it does not have a return value, but rather directs the user to a page on
785
- * api.dropbox.com where they are provided means to log in to Dropbox and grant authority to the application requesting it.
786
- * The page served by oauth/authorize should be presented to the user through their web browser.
787
- * Please note, without directing the user to a Dropbox-provided page via oauth/authorize, it is impossible for your application to use the request token it received
788
- * via oauth/request_token to obtain an access token from oauth/access_token.
789
- *
790
- * @return void
791
- * @param string $oauthToken The request token of the application requesting authority from a user.
792
- * @param string[optional] $oauthCallback After the user authorizes an application, the user is redirected to the application-served URL provided by this parameter.
793
- */
794
- public function oAuthAuthorize($oauthToken, $oauthCallback = null)
795
- {
796
- // build parameters
797
- $parameters = array();
798
- $parameters['oauth_token'] = (string) $oauthToken;
799
- if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
800
-
801
- // build url
802
- $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
803
-
804
- // redirect
805
- header('Location: ' . $url);
806
- exit;
807
- }
808
-
809
- public function mwp_oAuthAuthorize($oauthToken, $oauthCallback = null)
810
- {
811
- // build parameters
812
- $parameters = array();
813
- $parameters['oauth_token'] = (string) $oauthToken;
814
- if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
815
-
816
- // build url
817
- $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
818
-
819
- return $url;
820
- }
821
-
822
- /**
823
- * This call returns a access token and the corresponding access token secret.
824
- * Upon return, the authorization process is now complete and the access token and corresponding secret are used to sign requests for the metadata and file content API calls.
825
- *
826
- * @return array
827
- * @param string $oauthToken The token returned after authorizing.
828
- */
829
- public function oAuthAccessToken($oauthToken)
830
- {
831
- // build parameters
832
- $parameters = array();
833
- $parameters['oauth_token'] = (string) $oauthToken;
834
-
835
- // make the call
836
- $response = $this->doOAuthCall('1/oauth/access_token', $parameters, 'POST', false);
837
-
838
- // process response
839
- $response = (array) explode('&', $response);
840
- $return = array();
841
-
842
- // loop chunks
843
- foreach($response as $chunk)
844
- {
845
- // split again
846
- $chunks = explode('=', $chunk, 2);
847
-
848
- // store return
849
- if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
850
- }
851
-
852
- // return
853
- return $return;
854
- }
855
-
856
-
857
- // token resources
858
- /**
859
- * The token call provides a consumer/secret key pair you can use to consistently access the user's account.
860
- * This is the preferred method of authentication over storing the username and password.
861
- * Use the key pair as a signature with every subsequent call.
862
- * The request must be signed using the application's developer and secret key token. Request or access tokens are necessary.
863
- *
864
- * Warning: DO NOT STORE THE USER'S PASSWORD! The way this call works is you call it once with the user's email and password and then
865
- * keep the token around for later. You do NOT (I repeat NOT) call this before everything you do or on each program startup.
866
- * We watch for this and will shut down your application with little notice if we catch you.
867
- * In fact, the Objective-C code does this for you so you can't get it wrong.
868
- *
869
- * @return array Upon successful verification of the user's credentials, returns an array representation of the access token and secret.
870
- * @param string $email The email account of the user.
871
- * @param string $password The password of the user.
872
- */
873
- public function token($email, $password)
874
- {
875
- // build parameters
876
- $parameters = array();
877
- $parameters['email'] = (string) $email;
878
- $parameters['password'] = (string) $password;
879
-
880
- // make the call
881
- $response = (array) $this->doOAuthCall('1/token', $parameters);
882
-
883
- // validate and set
884
- if(isset($response['token'])) $this->setOAuthToken($response['token']);
885
- if(isset($response['secret'])) $this->setOAuthTokenSecret($response['secret']);
886
-
887
- // return
888
- return $response;
889
- }
890
-
891
-
892
- // account resources
893
- /**
894
- * Given a set of account information, the account call allows an application to create a new Dropbox user account.
895
- * This is useful for situations where the trusted third party application is possibly the user's first interaction with Dropbox.
896
- *
897
- * @return bool
898
- * @param string $email The email account of the user.
899
- * @param string $password The password for the user.
900
- * @param string $firstName The user's first name.
901
- * @param string $lastName The user's last name.
902
- */
903
- public function account($email, $password, $firstName, $lastName)
904
- {
905
- // build parameters
906
- $parameters['email'] = (string) $email;
907
- $parameters['first_name'] = (string) $firstName;
908
- $parameters['last_name'] = (string) $lastName;
909
- $parameters['password'] = (string) $password;
910
-
911
- return (bool) ($this->doCall('1/account', $parameters, 'POST', null, false) == 'OK');
912
- }
913
-
914
-
915
- /**
916
- * Get the user account information.
917
- *
918
- * @return array
919
- */
920
- public function accountInfo()
921
- {
922
- // make the call
923
- return (array) $this->doCall('1/account/info');
924
- }
925
-
926
-
927
- // files & metadata
928
- /**
929
- * Retrieves file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
930
- *
931
- * @return string
932
- * @param string $path Path of the directory wherin the file is located.
933
- * @param bool[optional] $sandbox Sandbox mode?
934
- */
935
- public function filesGet($path, $sandbox = false)
936
- {
937
- // build url
938
- $url = '1/files/';
939
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
940
- $url .= trim((string) $path, '/');
941
-
942
- // make the call
943
- return $this->doCall($url, null, 'GET', null, false, true);
944
- }
945
-
946
-
947
- /**
948
- * Uploads file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
949
- *
950
- * @return bool
951
- * @param string $path Path of the directory wherin the file should be uploaded.
952
- * @param string $localFile Path to the local file.
953
- * @param bool[optional] $sandbox Sandbox mode?
954
- */
955
- public function filesPost($path, $localFile, $sandbox = false)
956
- {
957
- // build url
958
- $url = '1/files/';
959
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
960
- $url .= trim((string) $path, '/');
961
-
962
- // make the call
963
- $return = $this->doCall($url, null, 'POST', $localFile, true, true);
964
- // return the result
965
- return (bool) (isset($return['size']) && $return['size'] == 'winner!');
966
- }
967
-
968
-
969
- /**
970
- * Returns metadata for the file or directory at the given <path> location relative to the user's Dropbox or
971
- * the user's application sandbox. If <path> represents a directory and the list parameter is true, the metadata will
972
- * also include a listing of metadata for the directory's contents.
973
- *
974
- * @return array
975
- * @param string[optional] $path The path to the file/director to get the metadata for.
976
- * @param int[optional] $fileLimit When listing a directory, the service will not report listings containing more than $fileLimit files.
977
- * @param bool[optional] $hash Listing return values include a hash representing the state of the directory's contents.
978
- * @param bool[optional] $list If true, this call returns a list of metadata representations for the contents of the directory. If false, this call returns the metadata for the directory itself.
979
- * @param bool[optional] $sandbox Sandbox mode?
980
- */
981
- public function metadata($path = '', $fileLimit = 10000, $hash = false, $list = true, $sandbox = false)
982
- {
983
- // build url
984
- $url = '1/metadata/';
985
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
986
- $url .= trim((string) $path, '/');
987
-
988
- // build parameters
989
- $parameters = null;
990
- $parameters['file_limit'] = (int) $fileLimit;
991
- if((bool) $hash) $parameters['hash'] = '';
992
- $parameters['list'] = ($list) ? 'true': 'false';
993
-
994
- // make the call
995
- return (array) $this->doCall($url, $parameters);
996
- }
997
-
998
-
999
- /**
1000
- * Get a minimized thumbnail for a photo.
1001
- *
1002
- * @return string Will return a base64_encode string with the JPEG-data
1003
- * @param string $path The path to the photo.
1004
- * @param string[optional] $size The size, possible values are: 'small' (32x32), 'medium' (64x64), 'large' (128x128).
1005
- */
1006
- public function thumbnails($path, $size = 'small')
1007
- {
1008
- // build url
1009
- $url = '1/thumbnails/dropbox/';
1010
- $url .= trim((string) $path, '/');
1011
-
1012
- // build parameters
1013
- $parameters['size'] = (string) $size;
1014
-
1015
- // make the call
1016
- return $this->doCall($url, $parameters, 'GET', null, false, true);
1017
- }
1018
-
1019
-
1020
- // file operations
1021
- /**
1022
- * Copy a file or folder to a new location.
1023
- *
1024
- * @return array
1025
- * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1026
- * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1027
- * @param bool[optional] $sandbox Sandbox mode?
1028
- */
1029
- public function fileopsCopy($fromPath, $toPath, $sandbox = false)
1030
- {
1031
- // build url
1032
- $url = '1/fileops/copy';
1033
-
1034
- // build parameters
1035
- $parameters['from_path'] = (string) $fromPath;
1036
- $parameters['to_path'] = (string) $toPath;
1037
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1038
-
1039
- // make the call
1040
- return $this->doCall($url, $parameters, 'POST');
1041
- }
1042
-
1043
-
1044
- /**
1045
- * Create a folder relative to the user's Dropbox root or the user's application sandbox folder.
1046
- *
1047
- * @return array
1048
- * @param string $path The path to the new folder to create, relative to root.
1049
- * @param bool[optional] $sandbox Sandbox mode?
1050
- */
1051
- public function fileopsCreateFolder($path, $sandbox = false)
1052
- {
1053
- // build url
1054
- $url = '1/fileops/create_folder';
1055
-
1056
- // build parameters
1057
- $parameters['path'] = trim((string) $path, '/');
1058
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1059
-
1060
- // make the call
1061
- return $this->doCall($url, $parameters, 'POST');
1062
- }
1063
-
1064
-
1065
- /**
1066
- * Deletes a file or folder.
1067
- *
1068
- * @return array
1069
- * @param string $path path specifies either a file or folder to be deleted. This path is interpreted relative to the location specified by root.
1070
- * @param bool[optional] $sandbox Sandbox mode?
1071
- */
1072
- public function fileopsDelete($path, $sandbox = false)
1073
- {
1074
- // build url
1075
- $url = '1/fileops/delete';
1076
-
1077
- // build parameters
1078
- $parameters['path'] = trim((string) $path, '/');
1079
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1080
- // make the call
1081
- return $this->doCall($url, $parameters, 'POST');
1082
- }
1083
-
1084
-
1085
- /**
1086
- * Move a file or folder to a new location.
1087
- *
1088
- * @return array
1089
- * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1090
- * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1091
- * @param bool[optional] $sandbox Sandbox mode?
1092
- */
1093
- public function fileopsMove($fromPath, $toPath, $sandbox = false)
1094
- {
1095
- // build url
1096
- $url = '1/fileops/move';
1097
-
1098
- // build parameters
1099
- $parameters['from_path'] = (string) $fromPath;
1100
- $parameters['to_path'] = (string) $toPath;
1101
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1102
-
1103
- // make the call
1104
- return $this->doCall($url, $parameters, 'POST');
1105
- }
1106
-
1107
- function _log($mixed)
1108
- {
1109
- if (is_array($mixed)) {
1110
- $mixed = print_r($mixed, 1);
1111
- } else if (is_object($mixed)) {
1112
- ob_start();
1113
- var_dump($mixed);
1114
- $mixed = ob_get_clean();
1115
- }
1116
-
1117
- $handle = fopen(dirname(__FILE__) . '/log', 'a');
1118
- fwrite($handle, $mixed . PHP_EOL);
1119
- fclose($handle);
1120
- }
1121
- }
1122
-
1123
-
1124
- /**
1125
- * Dropbox Exception class
1126
- *
1127
- * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
1128
- */
1129
- class DropboxException extends Exception
1130
- {
1131
- }
1132
-
1133
- ?>
1134
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/dropbox.php CHANGED
@@ -1,144 +1,283 @@
1
  <?php
2
- /**
3
- * Dropbox Uploader
4
- *
5
- * Copyright (c) 2009 Jaka Jancar
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * @author Jaka Jancar [jaka@kubje.org] [http://jaka.kubje.org/]
26
- * @version 1.1.5
27
- */
28
- class DropboxUploader {
29
- protected $email;
30
- protected $password;
31
- protected $caCertSourceType = self::CACERT_SOURCE_SYSTEM;
32
- const CACERT_SOURCE_SYSTEM = 0;
33
- const CACERT_SOURCE_FILE = 1;
34
- const CACERT_SOURCE_DIR = 2;
35
- protected $caCertSource;
36
- protected $loggedIn = false;
37
- protected $cookies = array();
38
-
39
- /**
40
- * Constructor
41
- *
42
- * @param string $email
43
- * @param string|null $password
44
- */
45
- public function __construct($email, $password) {
46
- // Check requirements
47
- if (!extension_loaded('curl'))
48
- throw new Exception('DropboxUploader requires the cURL extension.');
49
-
50
- $this->email = $email;
51
- $this->password = $password;
52
- }
53
-
54
- public function setCaCertificateFile($file)
55
- {
56
- $this->caCertSourceType = self::CACERT_SOURCE_FILE;
57
- $this->caCertSource = $file;
58
- }
59
-
60
- public function setCaCertificateDir($dir)
61
- {
62
- $this->caCertSourceType = self::CACERT_SOURCE_DIR;
63
- $this->caCertSource = $dir;
64
- }
65
-
66
- public function upload($filename, $remoteDir='/') {
67
- if (!file_exists($filename) or !is_file($filename) or !is_readable($filename))
68
- throw new Exception("File '$filename' does not exist or is not readable.");
69
-
70
- if (!is_string($remoteDir))
71
- throw new Exception("Remote directory must be a string, is ".gettype($remoteDir)." instead.");
72
-
73
- if (!$this->loggedIn)
74
- $this->login();
75
-
76
- $data = $this->request('https://www.dropbox.com/home');
77
- $token = $this->extractToken($data, 'https://dl-web.dropbox.com/upload');
78
-
79
- $data = $this->request('https://dl-web.dropbox.com/upload', true, array('plain'=>'yes', 'file'=>'@'.$filename, 'dest'=>$remoteDir, 't'=>$token));
80
- if (strpos($data, 'HTTP/1.1 302 FOUND') === false)
81
- throw new Exception('Upload failed!');
82
- }
83
-
84
- protected function login() {
85
- $data = $this->request('https://www.dropbox.com/login');
86
- $token = $this->extractToken($data, '/login');
87
-
88
- $data = $this->request('https://www.dropbox.com/login', true, array('login_email'=>$this->email, 'login_password'=>$this->password, 't'=>$token));
89
-
90
- if (stripos($data, 'location: /home') === false)
91
- throw new Exception('Login unsuccessful.');
92
-
93
- $this->loggedIn = true;
94
- }
95
 
96
- protected function request($url, $post=false, $postData=array()) {
97
- $ch = curl_init();
98
- curl_setopt($ch, CURLOPT_URL, $url);
99
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
100
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
101
- switch ($this->caCertSourceType) {
102
- case self::CACERT_SOURCE_FILE:
103
- curl_setopt($ch, CURLOPT_CAINFO, $this->caCertSource);
104
- break;
105
- case self::CACERT_SOURCE_DIR:
106
- curl_setopt($ch, CURLOPT_CAPATH, $this->caCertSource);
107
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
- curl_setopt($ch, CURLOPT_HEADER, 1);
110
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
111
- if ($post) {
112
- curl_setopt($ch, CURLOPT_POST, $post);
113
- curl_setopt($ch, CURLOPT_POSTFIELDS, array_map('stripcslashes', $postData));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
-
116
- // Send cookies
117
- $rawCookies = array();
118
- foreach ($this->cookies as $k=>$v)
119
- $rawCookies[] = "$k=$v";
120
- $rawCookies = implode(';', $rawCookies);
121
- curl_setopt($ch, CURLOPT_COOKIE, $rawCookies);
122
-
123
- $data = curl_exec($ch);
124
-
125
- if ($data === false)
126
- throw new Exception('Cannot execute request: '.curl_error($ch));
127
-
128
- // Store received cookies
129
- preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER);
130
- foreach ($matches as $match)
131
- $this->cookies[$match[1]] = $match[2];
132
-
133
- curl_close($ch);
134
-
135
- return $data;
136
  }
137
 
138
- protected function extractToken($html, $formAction) {
139
- if (!preg_match('/<form [^>]*'.preg_quote($formAction, '/').'[^>]*>.*?(<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is', $html, $matches) || !isset($matches[2]))
140
- throw new Exception("Cannot extract token! (form action=$formAction)");
141
- return $matches[2];
142
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
 
144
  }
 
1
  <?php
2
+ class Dropbox {
3
+ const API_URL = 'https://api.dropbox.com/';
4
+ const API_CONTENT_URL = 'https://api-content.dropbox.com/';
5
+ const API_WWW_URL = 'https://www.dropbox.com/';
6
+ const API_VERSION_URL = '1/';
7
+
8
+ private $root;
9
+ private $ProgressFunction = false;
10
+ private $oauth_app_key;
11
+ private $oauth_app_secret;
12
+ private $oauth_token;
13
+ private $oauth_token_secret;
14
+
15
+ public function __construct($oauth_app_key, $oauth_app_secret, $dropbox=false) {
16
+ $this->oauth_app_key = $oauth_app_key;
17
+ $this->oauth_app_secret = $oauth_app_secret;
18
+
19
+ if ($dropbox)
20
+ $this->root = 'dropbox';
21
+ else
22
+ $this->root = 'sandbox';
23
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ public function setOAuthTokens($token,$secret) {
26
+ $this->oauth_token = $token;
27
+ $this->oauth_token_secret = $secret;
28
+ }
29
+
30
+ public function setProgressFunction($function=null) {
31
+ if (function_exists($function))
32
+ $this->ProgressFunction = $function;
33
+ else
34
+ $this->ProgressFunction = false;
35
+ }
36
+
37
+ public function accountInfo(){
38
+ $url = self::API_URL.self::API_VERSION_URL.'account/info';
39
+ return $this->request($url);
40
+ }
41
+
42
+ public function upload($file, $path = '',$overwrite=true){
43
+ $file = str_replace("\\", "/",$file);
44
+ if (!is_readable($file) or !is_file($file))
45
+ throw new DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
46
+ $filesize=filesize($file);
47
+ if ($filesize<150000000) { //chunk transfer on bigger uploads <150MB
48
+ $filehandle = fopen($file,'r');
49
+ $url = self::API_CONTENT_URL.self::API_VERSION_URL.'files_put/'.$this->root.'/'.trim($path, '/');
50
+ $output = $this->request($url, array('overwrite' => ($overwrite)? 'true' : 'false'), 'PUT', $filehandle, $filesize);
51
+ fclose($filehandle);
52
+ } else {
53
+ $output = $this->chunked_upload($file, $path,$overwrite);
54
  }
55
+ return $output;
56
+ }
57
+
58
+ public function chunked_upload($file, $path = '',$overwrite=true){
59
+ $file = str_replace("\\", "/",$file);
60
+ if (!is_readable($file) or !is_file($file))
61
+ throw new DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
62
+ $file_handle=fopen($file,'r');
63
+ $uploadid=null;
64
+ $offset=0;
65
+ $ProgressFunction=null;
66
+ while ($data=fread($file_handle,4194304)) { //4194304 = 4MB
67
+ $chunkHandle = fopen('php://memory', 'rw');
68
+ fwrite($chunkHandle,$data);
69
+ rewind($chunkHandle);
70
+ //overwrite progress function
71
+ if (!empty($this->ProgressFunction) and function_exists($this->ProgressFunction)) {
72
+ $ProgressFunction=$this->ProgressFunction;
73
+ $this->ProgressFunction=false;
74
+ }
75
+ $url = self::API_CONTENT_URL.self::API_VERSION_URL.'chunked_upload';
76
+ $output = $this->request($url, array('upload_id' => $uploadid,'offset'=>$offset), 'PUT', $chunkHandle, strlen($data));
77
+ fclose($chunkHandle);
78
+ if ($ProgressFunction) {
79
+ call_user_func($ProgressFunction,0,0,0,$offset);
80
+ $this->ProgressFunction=$ProgressFunction;
81
+ }
82
+ //args for next chunk
83
+ $offset=$output['offset'];
84
+ $uploadid=$output['upload_id'];
85
+ fseek($file_handle,$offset);
86
  }
87
+ fclose($file_handle);
88
+ $url = self::API_CONTENT_URL.self::API_VERSION_URL.'commit_chunked_upload/'.$this->root.'/'.trim($path, '/');
89
+ return $this->request($url, array('overwrite' => ($overwrite)? 'true' : 'false','upload_id'=>$uploadid), 'POST');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
 
92
+ public function download($path,$echo=false){
93
+ $url = self::API_CONTENT_URL.self::API_VERSION_URL.'files/'.$this->root.'/'.trim($path,'/');
94
+ if (!$echo)
95
+ return $this->request($url);
96
+ else
97
+ $this->request($url,'','GET','','',true);
98
+ }
99
+
100
+ public function metadata($path = '', $listContents = true, $fileLimit = 10000){
101
+ $url = self::API_URL.self::API_VERSION_URL.'metadata/'.$this->root.'/'.trim($path,'/');
102
+ return $this->request($url, array('list' => ($listContents)? 'true' : 'false', 'file_limit' => $fileLimit));
103
+ }
104
+
105
+ public function search($path = '', $query , $fileLimit = 1000){
106
+ if (strlen($query)>=3)
107
+ throw new DropboxException("Error: Query \"$query\" must three characters long.");
108
+ $url = self::API_URL.self::API_VERSION_URL.'search/'.$this->root.'/'.trim($path,'/');
109
+ return $this->request($url, array('query' => $query, 'file_limit' => $fileLimit));
110
+ }
111
+
112
+ public function shares($path = ''){
113
+ $url = self::API_URL.self::API_VERSION_URL.'shares/'.$this->root.'/'.trim($path,'/');
114
+ return $this->request($url);
115
+ }
116
+
117
+ public function media($path = ''){
118
+ $url = self::API_URL.self::API_VERSION_URL.'media/'.$this->root.'/'.trim($path,'/');
119
+ return $this->request($url);
120
+ }
121
+
122
+ public function fileopsDelete($path){
123
+ $url = self::API_URL.self::API_VERSION_URL.'fileops/delete';
124
+ return $this->request($url, array('path' => '/'.trim($path,'/'), 'root' => $this->root));
125
+ }
126
+
127
+ public function fileopsCreate_folder($path){
128
+ $url = self::API_URL.self::API_VERSION_URL.'fileops/create_folder';
129
+ return $this->request($url, array('path' => '/'.trim($path,'/'), 'root' => $this->root));
130
+ }
131
+
132
+ public function oAuthAuthorize($callback_url) {
133
+ $headers[] = 'Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_signature="'.$this->oauth_app_secret.'&"';
134
+ $ch = curl_init();
135
+ curl_setopt($ch, CURLOPT_URL, self::API_URL . self::API_VERSION_URL . 'oauth/request_token' );
136
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
137
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
138
+ curl_setopt($ch, CURLOPT_SSLVERSION,3);
139
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
140
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
141
+ if (is_file(dirname(__FILE__).'/aws/lib/requestcore/cacert.pem'))
142
+ curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/aws/lib/requestcore/cacert.pem');
143
+ curl_setopt($ch, CURLOPT_AUTOREFERER , true);
144
+ curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
145
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
146
+ $content = curl_exec($ch);
147
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
148
+ if ($status>=200 and $status<300 and 0==curl_errno($ch) ) {
149
+ parse_str($content, $oauth_token);
150
+ } else {
151
+ $output = json_decode($content, true);
152
+ if(isset($output['error']) && is_string($output['error'])) $message = $output['error'];
153
+ elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) $output['error']['hash'];
154
+ elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
155
+ else $message = '('.$status.') Invalid response.';
156
+ throw new DropboxException($message);
157
+ }
158
+ curl_close($ch);
159
+ return array( 'authurl' => self::API_WWW_URL . self::API_VERSION_URL . 'oauth/authorize?oauth_token='.$oauth_token['oauth_token'].'&oauth_callback='.urlencode($callback_url),
160
+ 'oauth_token' => $oauth_token['oauth_token'],
161
+ 'oauth_token_secret'=> $oauth_token['oauth_token_secret'] );
162
+ }
163
+
164
+ public function oAuthAccessToken($oauth_token, $oauth_token_secret) {
165
+ $headers[] = 'Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_token="'.$oauth_token.'", oauth_signature="'.$this->oauth_app_secret.'&'.$oauth_token_secret.'"';
166
+ $ch = curl_init();
167
+ curl_setopt($ch, CURLOPT_URL, self::API_URL . self::API_VERSION_URL . 'oauth/access_token' );
168
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
169
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
170
+ curl_setopt($ch, CURLOPT_SSLVERSION,3);
171
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
172
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
173
+ if (is_file(dirname(__FILE__).'/aws/lib/requestcore/cacert.pem'))
174
+ curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/aws/lib/requestcore/cacert.pem');
175
+ curl_setopt($ch, CURLOPT_AUTOREFERER , true);
176
+ curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
177
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
178
+ $content = curl_exec($ch);
179
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
180
+ if ($status>=200 and $status<300 and 0==curl_errno($ch)) {
181
+ parse_str($content, $oauth_token);
182
+ $this->setOAuthTokens($oauth_token['oauth_token'], $oauth_token['oauth_token_secret']);
183
+ return $oauth_token;
184
+ } else {
185
+ $output = json_decode($content, true);
186
+ if(isset($output['error']) && is_string($output['error'])) $message = $output['error'];
187
+ elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) $output['error']['hash'];
188
+ elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
189
+ else $message = '('.$status.') Invalid response.';
190
+ throw new DropboxException($message);
191
+ }
192
+ }
193
+
194
+ private function request($url, $args = null, $method = 'GET', $filehandle = null, $filesize=0, $echo=false){
195
+ $args = (is_array($args)) ? $args : array();
196
+ $url = $this->url_encode($url);
197
+
198
+ /* Header*/
199
+ $headers[]='Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_token="'.$this->oauth_token.'", oauth_signature="'.$this->oauth_app_secret.'&'.$this->oauth_token_secret.'"';
200
+ $headers[]='Expect:';
201
+
202
+ /* Build cURL Request */
203
+ $ch = curl_init();
204
+ if ($method == 'POST') {
205
+ curl_setopt($ch, CURLOPT_POST, true);
206
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
207
+ curl_setopt($ch, CURLOPT_URL, $url);
208
+ } elseif ($method == 'PUT') {
209
+ curl_setopt($ch,CURLOPT_PUT,true);
210
+ curl_setopt($ch,CURLOPT_INFILE,$filehandle);
211
+ curl_setopt($ch,CURLOPT_INFILESIZE,$filesize);
212
+ $args = (is_array($args)) ? '?'.http_build_query($args, '', '&') : $args;
213
+ curl_setopt($ch, CURLOPT_URL, $url.$args);
214
+ } else {
215
+ $args = (is_array($args)) ? '?'.http_build_query($args, '', '&') : $args;
216
+ curl_setopt($ch, CURLOPT_URL, $url.$args);
217
+ }
218
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
219
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
220
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
221
+ curl_setopt($ch, CURLOPT_SSLVERSION,3);
222
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
223
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
224
+ if (is_file(dirname(__FILE__).'/aws/lib/requestcore/cacert.pem'))
225
+ curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/aws/lib/requestcore/cacert.pem');
226
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
227
+ curl_setopt($ch, CURLINFO_HEADER_OUT, true);
228
+ if (!empty($this->ProgressFunction) and function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION') and $method == 'PUT') {
229
+ curl_setopt($ch, CURLOPT_NOPROGRESS, false);
230
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
231
+ curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
232
+ }
233
+ if ($echo) {
234
+ echo curl_exec($ch);
235
+ $output='';
236
+ } else {
237
+ $content = curl_exec($ch);
238
+ $output = json_decode($content, true);
239
+ }
240
+ $status = curl_getinfo($ch);
241
+
242
+ if (isset($output['error']) or $status['http_code']>=300 or $status['http_code']<200 or curl_errno($ch)>0) {
243
+ if(isset($output['error']) && is_string($output['error'])) $message = '('.$status['http_code'].') '.$output['error'];
244
+ elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) '('.$status['http_code'].') '.$output['error']['hash'];
245
+ elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
246
+ elseif ($status['http_code']==304) $message = '(304) The folder contents have not changed (relies on hash parameter).';
247
+ elseif ($status['http_code']==400) $message = '(400) Bad input parameter: '.strip_tags($content);
248
+ elseif ($status['http_code']==401) $message = '(401) Bad or expired token. This can happen if the user or Dropbox revoked or expired an access token. To fix, you should re-authenticate the user.';
249
+ elseif ($status['http_code']==403) $message = '(403) Bad OAuth request (wrong consumer key, bad nonce, expired timestamp, ...). Unfortunately, reauthenticating the user won\'t help here.';
250
+ elseif ($status['http_code']==404) $message = '(404) The file was not found at the specified path, or was not found at the specified rev.';
251
+ elseif ($status['http_code']==405) $message = '(405) Request method not expected (generally should be GET,PUT or POST).';
252
+ elseif ($status['http_code']==406) $message = '(406) There are too many file entries to return.';
253
+ elseif ($status['http_code']==411) $message = '(411) Chunked encoding was attempted for this upload, but is not supported by Dropbox.';
254
+ elseif ($status['http_code']==415) $message = '(415) The image is invalid and cannot be thumbnailed.';
255
+ elseif ($status['http_code']==503) $message = '(503) Your app is making too many requests and is being rate limited. 503s can trigger on a per-app or per-user basis.';
256
+ elseif ($status['http_code']==507) $message = '(507) User is over Dropbox storage quota.';
257
+ else $message = '('.$status['http_code'].') Invalid response.';
258
+ throw new DropboxException($message);
259
+ } else {
260
+ curl_close($ch);
261
+ if (!is_array($output))
262
+ return $content;
263
+ else
264
+ return $output;
265
+ }
266
+ }
267
+
268
+ private function url_encode($string) {
269
+ $string = str_replace('?','%3F',$string);
270
+ $string = str_replace('=','%3D',$string);
271
+ $string = str_replace(' ','%20',$string);
272
+ $string = str_replace('(','%28',$string);
273
+ $string = str_replace(')','%29',$string);
274
+ $string = str_replace('&','%26',$string);
275
+ $string = str_replace('@','%40',$string);
276
+ return $string;
277
+ }
278
+
279
+ }
280
 
281
+ class DropboxException extends Exception {
282
  }
283
+ ?>
post.class.php CHANGED
@@ -1,751 +1,754 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * post.class.php
5
- *
6
- * Create remote post
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "post.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Post extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- function create($args)
23
- {
24
-
25
- //$this->_log($args);
26
- global $wpdb;
27
-
28
- /**
29
- * algorithm
30
- * 1. create post using wp_insert_post (insert tags also here itself)
31
- * 2. use wp_create_categories() to create(not exists) and insert in the post
32
- * 3. insert meta values
33
- */
34
-
35
- include_once ABSPATH . 'wp-admin/includes/taxonomy.php';
36
- include_once ABSPATH . 'wp-admin/includes/image.php';
37
- include_once ABSPATH . 'wp-admin/includes/file.php';
38
-
39
- $post_struct = $args['post_data'];
40
-
41
- $post_data = $post_struct['post_data'];
42
- $new_custom = $post_struct['post_extras']['post_meta'];
43
- $post_categories = explode(',', $post_struct['post_extras']['post_categories']);
44
- $post_atta_img = $post_struct['post_extras']['post_atta_images'];
45
- $post_upload_dir = $post_struct['post_extras']['post_upload_dir'];
46
- $post_checksum = $post_struct['post_extras']['post_checksum'];
47
- $post_featured_img = $post_struct['post_extras']['featured_img'];
48
-
49
- $upload = wp_upload_dir();
50
-
51
- // create dynamic url RegExp
52
- $mwp_base_url = parse_url($post_upload_dir['url']);
53
- $mwp_regexp_url = $mwp_base_url['host'] . $mwp_base_url['path'];
54
- $rep = array(
55
- '/',
56
- '+',
57
- '.',
58
- ':',
59
- '?'
60
- );
61
- $with = array(
62
- '\/',
63
- '\+',
64
- '\.',
65
- '\:',
66
- '\?'
67
- );
68
- $mwp_regexp_url = str_replace($rep, $with, $mwp_regexp_url);
69
-
70
- // rename all src ../wp-content/ with hostname/wp-content/
71
- $mmb_dot_url = '..' . $mmb_base_url['path'];
72
- $mmb_dot_url = str_replace($rep, $with, $mmb_dot_url);
73
- $dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
74
- if ($dot_match_count > 0) {
75
- foreach ($dot_get_urls as $dot_url) {
76
- $match_dot = '/' . str_replace($rep, $with, $dot_url[4]) . '/';
77
- $replace_dot = 'http://' . $mmb_base_url['host'] . substr($dot_url[4], 2, strlen($dot_url[4]));
78
- $post_data['post_content'] = preg_replace($match_dot, $replace_dot, $post_data['post_content']);
79
-
80
- if ($dot_url[1] != '') {
81
- $match_dot_a = '/' . str_replace($rep, $with, $dot_url[2]) . '/';
82
- $replace_dot_a = 'http://' . $mmb_base_url['host'] . substr($dot_url[2], 2, strlen($dot_url[2]));
83
- $post_data['post_content'] = preg_replace($match_dot_a, $replace_dot_a, $post_data['post_content']);
84
- }
85
- }
86
- }
87
-
88
-
89
-
90
- //to find all the images
91
- $match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]+' . $mmb_regexp_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $get_urls, PREG_SET_ORDER);
92
- if ($match_count > 0) {
93
- $attachments = array();
94
- $post_content = $post_data['post_content'];
95
-
96
- foreach ($get_urls as $get_url_k => $get_url) {
97
- // unset url in attachment array
98
- foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
99
- $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
100
- if (preg_match($match_patt_url, $get_url[4])) {
101
- unset($post_atta_img[$atta_url_k]);
102
- }
103
- }
104
-
105
- if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
106
- if ($get_url[1] != '') {
107
- // change src url
108
- $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
109
-
110
- $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
111
- $s_mmb_rp = $s_img_atta[0];
112
- $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
113
- // change attachment url
114
- if (preg_match('/attachment_id/i', $get_url[2])) {
115
- $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
116
- $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
117
- $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
118
- }
119
- }
120
- continue;
121
- }
122
-
123
- $no_thumb = '';
124
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
125
- $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
126
- } else {
127
- $no_thumb = $get_url[4];
128
- }
129
-
130
- if(isset($upload['error']) && !empty($upload['error'])){
131
- return array('error' => $upload['error']);
132
- }
133
- $file_name = basename($no_thumb);
134
- $tmp_file = download_url($no_thumb);
135
-
136
- if(is_wp_error($tmp_file)){
137
- return array('error' => $tmp_file->get_error_message());
138
- }
139
-
140
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
141
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
142
- $renamed = @rename($tmp_file, $attach_upload['path']);
143
- if ($renamed === true) {
144
- $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
145
- $replace_pattern = $attach_upload['url'];
146
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
147
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
148
- $match_pattern = '/' . str_replace($rep, $with, preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4])) . '/';
149
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
150
- }
151
-
152
- $attachment = array(
153
- 'post_title' => $file_name,
154
- 'post_content' => '',
155
- 'post_type' => 'attachment',
156
- //'post_parent' => $post_id,
157
- 'post_mime_type' => 'image/' . $get_url[5],
158
- 'guid' => $attach_upload['url']
159
- );
160
-
161
- // Save the data
162
-
163
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
164
-
165
- $attachments[$attach_id] = 0;
166
-
167
- // featured image
168
- if ($post_featured_img != '') {
169
- $feat_img_url = '';
170
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
171
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
172
- } else {
173
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
174
- }
175
- $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
176
- if (preg_match($m_feat_url, $get_url[4])) {
177
- $post_featured_img = '';
178
- $attachments[$attach_id] = $attach_id;
179
- }
180
- }
181
-
182
- // set $get_urls value[6] - parent atta_id
183
- foreach ($get_urls as $url_k => $url_v) {
184
- if ($get_url_k != $url_k) {
185
- $s_get_url = '';
186
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
187
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
188
- } else {
189
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
190
- }
191
- $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
192
- if (preg_match($m_patt_url, $get_url[4])) {
193
- array_push($get_urls[$url_k], $attach_id);
194
- }
195
- }
196
- }
197
-
198
-
199
- $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
200
- wp_update_attachment_metadata($attach_id, $some_data);
201
-
202
-
203
- // changing href of a tag
204
- if ($get_url[1] != '') {
205
- $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
206
- if (preg_match('/attachment_id/i', $get_url[2])) {
207
- $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
208
- $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
209
- }
210
- }
211
- } else {
212
- @unlink($tmp_file);
213
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
214
-
215
- }
216
- @unlink($tmp_file);
217
- }
218
-
219
-
220
- $post_data['post_content'] = $post_content;
221
-
222
- }
223
- if (count($post_atta_img)) {
224
- foreach ($post_atta_img as $img) {
225
- $file_name = basename($img['src']);
226
-
227
- if(isset($upload['error']) && !empty($upload['error'])){
228
- return array('error' => $upload['error']);
229
- }
230
-
231
- $tmp_file = download_url($img['src']);
232
- if(is_wp_error($tmp_file)){
233
- return array('error' => $tmp_file->get_error_message());
234
- }
235
-
236
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
237
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
238
- $renamed = @rename($tmp_file, $attach_upload['path']);
239
- if ($renamed === true) {
240
- $atta_ext = end(explode('.', $file_name));
241
-
242
- $attachment = array(
243
- 'post_title' => $file_name,
244
- 'post_content' => '',
245
- 'post_type' => 'attachment',
246
- //'post_parent' => $post_id,
247
- 'post_mime_type' => 'image/' . $atta_ext,
248
- 'guid' => $attach_upload['url']
249
- );
250
-
251
- // Save the data
252
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
253
- wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
254
- $attachments[$attach_id] = 0;
255
-
256
- // featured image
257
- if ($post_featured_img != '') {
258
- $feat_img_url = '';
259
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
260
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
261
- } else {
262
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
263
- }
264
- $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
265
- if (preg_match($m_feat_url, $img['src'])) {
266
- $post_featured_img = '';
267
- $attachments[$attach_id] = $attach_id;
268
- }
269
- }
270
-
271
- } else {
272
- @unlink($tmp_file);
273
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
274
- }
275
- @unlink($tmp_file);
276
- }
277
- }
278
-
279
- //Prepare post data and temporarily remove content filters before insert post
280
- $user = $this->mmb_get_user_info( $args['username'] );
281
- if($user && $user->ID){
282
- $post_data['post_author'] = $user->ID;
283
- }
284
- //remove filter which can brake scripts or html
285
- remove_filter('content_save_pre', 'wp_filter_post_kses');
286
-
287
- //check for edit post
288
- $post_result = 0;
289
- if(isset($post_data['mwp_post_edit']) && $post_data['mwp_post_edit']){
290
-
291
-
292
- if($post_data['mwp_match_by'] == 'title'){
293
- $match_by = "post_title = '".$post_data['post_title']."'";
294
- } else {
295
- $match_by = "post_name = '".$post_data['post_name']."'";
296
- }
297
-
298
- $query = "SELECT ID FROM $wpdb->posts WHERE $match_by AND post_status NOT IN('inherit','auto-draft','draft') LIMIT 1";
299
-
300
- $post_result = $wpdb->get_var($query);
301
-
302
- }
303
-
304
-
305
- if($post_result){
306
- //update existing post
307
- $post_data['ID'] = $post_result;
308
- $post_id = wp_update_post($post_data);
309
-
310
- //check for previous attachments
311
- $atta_allimages =& get_children('post_type=attachment&post_parent=' . $post_id);
312
- if (!empty($atta_allimages)) {
313
- foreach ($atta_allimages as $image) {
314
- wp_delete_attachment($image->ID);
315
- }
316
- }
317
-
318
- } else {
319
- if($post_data['mwp_post_edit'] && $post_data['mwp_force_publish']){
320
- $post_id = wp_insert_post($post_data);
321
- } elseif($post_data['mwp_post_edit'] && !$post_data['mwp_force_publish']) {
322
- return array('error' => "Post not found.");
323
- } else {
324
- $post_id = wp_insert_post($post_data);
325
- }
326
-
327
- }
328
-
329
- if (count($attachments)) {
330
- foreach ($attachments as $atta_id => $featured_id) {
331
- $result = wp_update_post(array(
332
- 'ID' => $atta_id,
333
- 'post_parent' => $post_id
334
- ));
335
- if ($featured_id > 0) {
336
- $new_custom['_thumbnail_id'] = array(
337
- $featured_id
338
- );
339
- }
340
- }
341
- }
342
-
343
- // featured image
344
- if ($post_featured_img != '') {
345
- $file_name = basename($post_featured_img);
346
- if(isset($upload['error']) && !empty($upload['error'])){
347
- return array('error' => $upload['error']);
348
- }
349
- $tmp_file = download_url($post_featured_img);
350
- if(is_wp_error($tmp_file)){
351
- return array('error' => $tmp_file->get_error_message());
352
- }
353
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
354
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
355
- $renamed = @rename($tmp_file, $attach_upload['path']);
356
- if ($renamed === true) {
357
- $atta_ext = end(explode('.', $file_name));
358
-
359
- $attachment = array(
360
- 'post_title' => $file_name,
361
- 'post_content' => '',
362
- 'post_type' => 'attachment',
363
- 'post_parent' => $post_id,
364
- 'post_mime_type' => 'image/' . $atta_ext,
365
- 'guid' => $attach_upload['url']
366
- );
367
-
368
- // Save the data
369
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
370
- wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
371
- $new_custom['_thumbnail_id'] = array(
372
- $attach_id
373
- );
374
- } else {
375
- @unlink($tmp_file);
376
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
377
- }
378
- @unlink($tmp_file);
379
- }
380
-
381
- if ($post_id && is_array($post_categories)) {
382
- //insert categories
383
-
384
- $cat_ids = wp_create_categories($post_categories, $post_id);
385
- }
386
-
387
-
388
- //get current custom fields
389
- $cur_custom = get_post_custom($post_id);
390
- //check which values doesnot exists in new custom fields
391
- $diff_values = array_diff_key($cur_custom, $new_custom);
392
-
393
- if (is_array($diff_values))
394
- foreach ($diff_values as $meta_key => $value) {
395
- delete_post_meta($post_id, $meta_key);
396
- }
397
- //insert new post meta
398
- foreach ($new_custom as $meta_key => $value) {
399
- if (strpos($meta_key, '_mmb') === 0 || strpos($meta_key, '_edit') === 0) {
400
- continue;
401
- } else {
402
- update_post_meta($post_id, $meta_key, $value[0]);
403
- }
404
- }
405
- return $post_id;
406
- }
407
-
408
-
409
- function change_status($args)
410
- {
411
-
412
- global $wpdb;
413
- $post_id = $args['post_id'];
414
- $status = $args['status'];
415
- $success = false;
416
-
417
- if(in_array($status, array('draft', 'publish', 'trash'))){
418
- $sql = "update ".$wpdb->prefix."posts set post_status = '$status' where ID = '$post_id'";
419
- $success = $wpdb->query($sql);
420
- }
421
-
422
- return $success;
423
- }
424
-
425
- /*
426
- * Function which gets posts from worker depending on arguments.
427
- * If FROM and TO dates are provided and range, range has bigger priority to date FROM.
428
- * This means if there are less posts between FROM and TO than range provided,
429
- * this function omit date from and returns last range number posts to date TO.
430
- *
431
- * @param array $args arguments passed to function
432
- * @arg string filter_posts search phrase for post titles
433
- * @arg string mwp_get_posts_date_from date in format(Y-m-d H:i:s) when posts are publishes from
434
- * @arg string mwp_get_posts_date_to date in format(Y-m-d H:i:s) when posts are publishes to
435
- * @arg string mwp_get_posts_range range number of returned posts
436
- * @arg string mwp_get_posts_publish on or off
437
- * @arg string mwp_get_posts_pending on or off
438
- * @arg string mwp_get_posts_private on or off
439
- * @arg string mwp_get_posts_future on or off
440
- * @arg string mwp_get_posts_draft on or off
441
- * @arg string mwp_get_posts_trash on or off
442
- * @return array posts related to args
443
- */
444
- function get_posts($args){
445
- global $wpdb;
446
-
447
- $where='';
448
-
449
- extract($args);
450
-
451
- if(!empty($filter_posts))
452
- {
453
- $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_posts)."%'";
454
- }
455
-
456
- if(!empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
457
- {
458
- $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_posts_date_from)."' AND '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
459
- }
460
- else if(!empty($mwp_get_posts_date_from) && empty($mwp_get_posts_date_to))
461
- {
462
- $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_posts_date_from)."'";
463
- }
464
- else if(empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
465
- {
466
- $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
467
- }
468
- $post_array=array();
469
- $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
470
- foreach ($args as $checkbox => $checkbox_val)
471
- {
472
- if($checkbox_val=="on") {
473
- $post_array[]="'".str_replace("mwp_get_posts_","",$checkbox)."'";
474
- }
475
- }
476
- if(!empty($post_array))
477
- {
478
- $where.=" AND post_status IN (".implode(",",$post_array).")";
479
- }
480
-
481
- $limit = ($mwp_get_posts_range) ? ' LIMIT ' . mysql_real_escape_string($mwp_get_posts_range) : ' LIMIT 500';
482
-
483
- $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' ".$where." ORDER BY post_date DESC";
484
-
485
- $total = array();
 
 
 
486
  $posts = array();
487
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query.$limit);
488
- $user_info = $this->getUsersIDs();
489
- $post_cats=$this->getPostCats();
490
- $post_tags=$this->getPostCats('post_tag');
491
- $total['total_num']=count($posts_info);
492
-
493
- if($mwp_get_posts_range && !empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to) && $total['total_num'] < $mwp_get_posts_range) {
494
- $sql_query = "$wpdb->posts
495
- WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'
496
- ORDER BY post_date DESC
497
- LIMIT " . mysql_real_escape_string($mwp_get_posts_range);
498
-
499
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query);
500
- $total = array();
501
- $total['total_num']=count($posts_info);
502
- }
503
-
504
- foreach ( $posts_info as $post_info )
505
- {
506
-
507
- $cats=array();
508
- foreach($post_cats[$post_info->ID] as $cat_array => $cat_array_val)
509
- {
510
- $cats[] = array('name' => $cat_array_val);
511
- }
512
-
513
- $tags=array();
514
- if (!empty($post_tags[$post_info->ID])) {
515
- foreach($post_tags[$post_info->ID] as $tag_array => $tag_array_val)
516
- {
517
- $tags[] = array('name' => $tag_array_val);
518
- }
519
- }
520
-
521
- $posts[]=array(
522
- 'post_id'=>$post_info->ID,
523
- 'post_title'=>$post_info->post_title,
524
- 'post_name'=>$post_info->post_name,
525
- 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
526
- 'post_date'=>$post_info->post_date,
527
- 'post_modified'=>$post_info->post_modified,
528
- 'post_status'=>$post_info->post_status,
529
- 'post_type'=>$post_info->post_type,
530
- 'guid'=>$post_info->guid,
531
- 'post_password'=>$post_info->post_password,
532
- 'ping_status'=>$post_info->ping_status,
533
- 'comment_status'=>$post_info->comment_status,
534
- 'comment_count'=>$post_info->comment_count,
535
- 'cats'=>$cats,
536
- 'tags'=>$tags,
537
-
538
- );
539
- }
540
-
541
- return array('posts' => $posts, 'total' => $total);
542
- }
543
-
544
- function delete_post($args){
545
- global $wpdb;
546
- if(!empty($args['post_id']) && !empty($args['action']))
547
- {
548
- if($args['action']=='delete')
549
- {
550
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
551
- }
552
- else if($args['action']=='delete_perm'){
553
- $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
554
- }
555
- else if($args['action']=='delete_restore'){
556
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
557
- }
558
- $wpdb->get_results($delete_query);
559
-
560
- return 'Post deleted.';
561
- }
562
- else
563
- {
564
- return 'No ID...';
565
- }
566
- }
567
-
568
- function delete_posts($args){
569
- global $wpdb;
570
- extract($args);
571
- if($deleteaction=='delete'){
572
- $delete_query_intro = "DELETE FROM $wpdb->posts WHERE ID = ";
573
- }elseif($deleteaction=='trash'){
574
- $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ";
575
- }elseif($deleteaction=='draft'){
576
- $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = ";
577
- }elseif($deleteaction=='publish'){
578
- $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ";
579
- }
580
- foreach($args as $key=>$val){
581
-
582
- if(!empty($val) && is_numeric($val))
583
- {
584
- $delete_query = $delete_query_intro.$val;
585
-
586
- $wpdb->query($delete_query);
587
- }
588
- }
589
- return "Post deleted";
590
-
591
- }
592
-
593
- /*
594
  * Function which gets pages from worker depending on arguments.
595
  * If FROM and TO dates are provided and range, range has bigger priority to date FROM.
596
  * This means if there are less pages between FROM and TO than range provided,
597
- * this function omit date from and returns last range number pages to date TO.
598
- *
599
- * @param array $args arguments passed to function
600
- * @arg string filter_pages search phrase for page titles
601
- * @arg string mwp_get_pages_date_from date in format(Y-m-d H:i:s) when pages are publishes from
602
- * @arg string mwp_get_pages_date_to date in format(Y-m-d H:i:s) when pages are publishes to
603
- * @arg string mwp_get_pages_range range number of returned pages
604
- * @arg string mwp_get_pages_publish on or off
605
- * @arg string mwp_get_pages_pending on or off
606
- * @arg string mwp_get_pages_private on or off
607
- * @arg string mwp_get_pages_future on or off
608
- * @arg string mwp_get_pages_draft on or off
609
- * @arg string mwp_get_pages_trash on or off
610
  * @return array pages related to args
611
- */
612
- function get_pages($args){
613
- global $wpdb;
614
-
615
- $where='';
616
- extract($args);
617
-
618
- if(!empty($filter_pages))
619
- {
620
- $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_pages)."%'";
621
- }
622
- if(!empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
623
- {
624
- $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_pages_date_from)."' AND '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
625
- }
626
- else if(!empty($mwp_get_pages_date_from) && empty($mwp_get_pages_date_to))
627
- {
628
- $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_pages_date_from)."'";
629
- }
630
- else if(empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
631
- {
632
- $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
633
- }
634
-
635
- $post_array=array();
636
- $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
637
- foreach ($args as $checkbox => $checkbox_val)
638
- {
639
- if($checkbox_val=="on") {
640
- $post_array[]="'".str_replace("mwp_get_pages_","",$checkbox)."'";
641
- }
642
- }
643
- if(!empty($post_array))
644
- {
645
- $where.=" AND post_status IN (".implode(",",$post_array).")";
646
- }
647
-
648
- $limit = ($mwp_get_pages_range) ? ' LIMIT ' . mysql_real_escape_string($mwp_get_pages_range) : ' LIMIT 500';
649
-
650
- $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='page' ".$where.' ORDER BY post_date DESC';
651
-
652
- $total = array();
653
- $posts = array();
654
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query.$limit);
655
- $user_info = $this->getUsersIDs();
656
- $total['total_num']=count($posts_info);
657
-
658
- if($mwp_get_pages_range && !empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to) && $total['total_num'] < $mwp_get_pages_range) {
659
- $sql_query = "$wpdb->posts
660
- WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'
661
- ORDER BY post_date DESC
662
- LIMIT " . mysql_real_escape_string($mwp_get_pages_range);
663
-
664
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query);
665
- $total = array();
666
- $total['total_num']=count($posts_info);
667
- }
668
-
669
- foreach ( $posts_info as $post_info )
670
- {
671
-
672
- $posts[]=array(
673
- 'post_id'=>$post_info->ID,
674
- 'post_title'=>$post_info->post_title,
675
- 'post_name'=>$post_info->post_name,
676
- 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
677
- 'post_date'=>$post_info->post_date,
678
- 'post_modified'=>$post_info->post_modified,
679
- 'post_status'=>$post_info->post_status,
680
- 'post_type'=>$post_info->post_type,
681
- 'guid'=>$post_info->guid,
682
- 'post_password'=>$post_info->post_password,
683
- 'ping_status'=>$post_info->ping_status,
684
- 'comment_status'=>$post_info->comment_status,
685
- 'comment_count'=>$post_info->comment_count
686
-
687
- );
688
- }
689
-
690
- return array('posts' => $posts, 'total' => $total);
691
- }
692
-
693
- function delete_page($args){
694
- global $wpdb;
695
- if(!empty($args['post_id']) && !empty($args['action']))
696
- {
697
- if($args['action']=='delete')
698
- {
699
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
700
- }
701
- else if($args['action']=='delete_perm'){
702
- $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
703
- }
704
- else if($args['action']=='delete_restore'){
705
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
706
- }
707
- $wpdb->get_results($delete_query);
708
-
709
- return 'Page deleted.';
710
- }
711
- else
712
- {
713
- return 'No ID...';
714
- }
715
- }
716
-
717
- function getPostCats($taxonomy = 'category')
718
- {
719
- global $wpdb;
720
-
721
- $cats = $wpdb->get_results("SELECT p.ID AS post_id, $wpdb->terms.name
722
- FROM $wpdb->posts AS p
723
- INNER JOIN $wpdb->term_relationships ON ( p.ID = $wpdb->term_relationships.object_id )
724
- INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
725
- AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
726
- INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
727
-
728
- foreach ( $cats as $post_val )
729
- {
730
-
731
- $post_cats[$post_val->post_id][] = $post_val->name;
732
- }
733
-
734
- return $post_cats;
735
- }
736
-
737
- function getUsersIDs()
738
- {
739
- global $wpdb;
740
- $users_authors=array();
741
- $users = $wpdb->get_results("SELECT ID as user_id, display_name FROM $wpdb->users WHERE user_status=0");
742
-
743
- foreach ( $users as $user_key=>$user_val )
744
- {
745
- $users_authors[$user_val->user_id] = $user_val->display_name;
746
- }
747
-
748
- return $users_authors;
749
- }
750
- }
751
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * post.class.php
5
+ *
6
+ * Create remote post
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "post.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Post extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ function create($args)
23
+ {
24
+
25
+ //$this->_log($args);
26
+ global $wpdb;
27
+
28
+ /**
29
+ * algorithm
30
+ * 1. create post using wp_insert_post (insert tags also here itself)
31
+ * 2. use wp_create_categories() to create(not exists) and insert in the post
32
+ * 3. insert meta values
33
+ */
34
+
35
+ include_once ABSPATH . 'wp-admin/includes/taxonomy.php';
36
+ include_once ABSPATH . 'wp-admin/includes/image.php';
37
+ include_once ABSPATH . 'wp-admin/includes/file.php';
38
+
39
+ $post_struct = $args['post_data'];
40
+
41
+ $post_data = $post_struct['post_data'];
42
+ $new_custom = $post_struct['post_extras']['post_meta'];
43
+ $post_categories = explode(',', $post_struct['post_extras']['post_categories']);
44
+ $post_atta_img = $post_struct['post_extras']['post_atta_images'];
45
+ $post_upload_dir = $post_struct['post_extras']['post_upload_dir'];
46
+ $post_checksum = $post_struct['post_extras']['post_checksum'];
47
+ $post_featured_img = $post_struct['post_extras']['featured_img'];
48
+
49
+ $upload = wp_upload_dir();
50
+
51
+ // create dynamic url RegExp
52
+ $mwp_base_url = parse_url($post_upload_dir['url']);
53
+ $mwp_regexp_url = $mwp_base_url['host'] . $mwp_base_url['path'];
54
+ $rep = array(
55
+ '/',
56
+ '+',
57
+ '.',
58
+ ':',
59
+ '?'
60
+ );
61
+ $with = array(
62
+ '\/',
63
+ '\+',
64
+ '\.',
65
+ '\:',
66
+ '\?'
67
+ );
68
+ $mwp_regexp_url = str_replace($rep, $with, $mwp_regexp_url);
69
+
70
+ // rename all src ../wp-content/ with hostname/wp-content/
71
+ $mmb_dot_url = '..' . $mmb_base_url['path'];
72
+ $mmb_dot_url = str_replace($rep, $with, $mmb_dot_url);
73
+ $dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
74
+ if ($dot_match_count > 0) {
75
+ foreach ($dot_get_urls as $dot_url) {
76
+ $match_dot = '/' . str_replace($rep, $with, $dot_url[4]) . '/';
77
+ $replace_dot = 'http://' . $mmb_base_url['host'] . substr($dot_url[4], 2, strlen($dot_url[4]));
78
+ $post_data['post_content'] = preg_replace($match_dot, $replace_dot, $post_data['post_content']);
79
+
80
+ if ($dot_url[1] != '') {
81
+ $match_dot_a = '/' . str_replace($rep, $with, $dot_url[2]) . '/';
82
+ $replace_dot_a = 'http://' . $mmb_base_url['host'] . substr($dot_url[2], 2, strlen($dot_url[2]));
83
+ $post_data['post_content'] = preg_replace($match_dot_a, $replace_dot_a, $post_data['post_content']);
84
+ }
85
+ }
86
+ }
87
+
88
+
89
+
90
+ //to find all the images
91
+ $match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]+' . $mmb_regexp_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $get_urls, PREG_SET_ORDER);
92
+ if ($match_count > 0) {
93
+ $attachments = array();
94
+ $post_content = $post_data['post_content'];
95
+
96
+ foreach ($get_urls as $get_url_k => $get_url) {
97
+ // unset url in attachment array
98
+ foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
99
+ $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
100
+ if (preg_match($match_patt_url, $get_url[4])) {
101
+ unset($post_atta_img[$atta_url_k]);
102
+ }
103
+ }
104
+ $pic_from_other_site = $get_urls[$get_url_k][4];
105
+ if(strpos($pic_from_other_site,'managewp.com') === false){
106
+ continue;
107
+ }
108
+ if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
109
+ if ($get_url[1] != '') {
110
+ // change src url
111
+ $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
112
+
113
+ $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
114
+ $s_mmb_rp = $s_img_atta[0];
115
+ $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
116
+ // change attachment url
117
+ if (preg_match('/attachment_id/i', $get_url[2])) {
118
+ $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
119
+ $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
120
+ $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
121
+ }
122
+ }
123
+ continue;
124
+ }
125
+
126
+ $no_thumb = '';
127
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
128
+ $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
129
+ } else {
130
+ $no_thumb = $get_url[4];
131
+ }
132
+
133
+ if(isset($upload['error']) && !empty($upload['error'])){
134
+ return array('error' => $upload['error']);
135
+ }
136
+ $file_name = basename($no_thumb);
137
+ $tmp_file = download_url($no_thumb);
138
+
139
+ if(is_wp_error($tmp_file)){
140
+ return array('error' => $tmp_file->get_error_message());
141
+ }
142
+
143
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
144
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
145
+ $renamed = @rename($tmp_file, $attach_upload['path']);
146
+ if ($renamed === true) {
147
+ $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
148
+ $replace_pattern = $attach_upload['url'];
149
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
150
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
151
+ $match_pattern = '/' . str_replace($rep, $with, preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4])) . '/';
152
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
153
+ }
154
+
155
+ $attachment = array(
156
+ 'post_title' => $file_name,
157
+ 'post_content' => '',
158
+ 'post_type' => 'attachment',
159
+ //'post_parent' => $post_id,
160
+ 'post_mime_type' => 'image/' . $get_url[5],
161
+ 'guid' => $attach_upload['url']
162
+ );
163
+
164
+ // Save the data
165
+
166
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
167
+
168
+ $attachments[$attach_id] = 0;
169
+
170
+ // featured image
171
+ if ($post_featured_img != '') {
172
+ $feat_img_url = '';
173
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
174
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
175
+ } else {
176
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
177
+ }
178
+ $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
179
+ if (preg_match($m_feat_url, $get_url[4])) {
180
+ $post_featured_img = '';
181
+ $attachments[$attach_id] = $attach_id;
182
+ }
183
+ }
184
+
185
+ // set $get_urls value[6] - parent atta_id
186
+ foreach ($get_urls as $url_k => $url_v) {
187
+ if ($get_url_k != $url_k) {
188
+ $s_get_url = '';
189
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
190
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
191
+ } else {
192
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
193
+ }
194
+ $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
195
+ if (preg_match($m_patt_url, $get_url[4])) {
196
+ array_push($get_urls[$url_k], $attach_id);
197
+ }
198
+ }
199
+ }
200
+
201
+
202
+ $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
203
+ wp_update_attachment_metadata($attach_id, $some_data);
204
+
205
+
206
+ // changing href of a tag
207
+ if ($get_url[1] != '') {
208
+ $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
209
+ if (preg_match('/attachment_id/i', $get_url[2])) {
210
+ $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
211
+ $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
212
+ }
213
+ }
214
+ } else {
215
+ @unlink($tmp_file);
216
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
217
+
218
+ }
219
+ @unlink($tmp_file);
220
+ }
221
+
222
+
223
+ $post_data['post_content'] = $post_content;
224
+
225
+ }
226
+ if (count($post_atta_img)) {
227
+ foreach ($post_atta_img as $img) {
228
+ $file_name = basename($img['src']);
229
+
230
+ if(isset($upload['error']) && !empty($upload['error'])){
231
+ return array('error' => $upload['error']);
232
+ }
233
+
234
+ $tmp_file = download_url($img['src']);
235
+ if(is_wp_error($tmp_file)){
236
+ return array('error' => $tmp_file->get_error_message());
237
+ }
238
+
239
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
240
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
241
+ $renamed = @rename($tmp_file, $attach_upload['path']);
242
+ if ($renamed === true) {
243
+ $atta_ext = end(explode('.', $file_name));
244
+
245
+ $attachment = array(
246
+ 'post_title' => $file_name,
247
+ 'post_content' => '',
248
+ 'post_type' => 'attachment',
249
+ //'post_parent' => $post_id,
250
+ 'post_mime_type' => 'image/' . $atta_ext,
251
+ 'guid' => $attach_upload['url']
252
+ );
253
+
254
+ // Save the data
255
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
256
+ wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
257
+ $attachments[$attach_id] = 0;
258
+
259
+ // featured image
260
+ if ($post_featured_img != '') {
261
+ $feat_img_url = '';
262
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
263
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
264
+ } else {
265
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
266
+ }
267
+ $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
268
+ if (preg_match($m_feat_url, $img['src'])) {
269
+ $post_featured_img = '';
270
+ $attachments[$attach_id] = $attach_id;
271
+ }
272
+ }
273
+
274
+ } else {
275
+ @unlink($tmp_file);
276
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
277
+ }
278
+ @unlink($tmp_file);
279
+ }
280
+ }
281
+
282
+ //Prepare post data and temporarily remove content filters before insert post
283
+ $user = $this->mmb_get_user_info( $args['username'] );
284
+ if($user && $user->ID){
285
+ $post_data['post_author'] = $user->ID;
286
+ }
287
+ //remove filter which can brake scripts or html
288
+ remove_filter('content_save_pre', 'wp_filter_post_kses');
289
+
290
+ //check for edit post
291
+ $post_result = 0;
292
+ if(isset($post_data['mwp_post_edit']) && $post_data['mwp_post_edit']){
293
+
294
+
295
+ if($post_data['mwp_match_by'] == 'title'){
296
+ $match_by = "post_title = '".$post_data['post_title']."'";
297
+ } else {
298
+ $match_by = "post_name = '".$post_data['post_name']."'";
299
+ }
300
+
301
+ $query = "SELECT ID FROM $wpdb->posts WHERE $match_by AND post_status NOT IN('inherit','auto-draft','draft') LIMIT 1";
302
+
303
+ $post_result = $wpdb->get_var($query);
304
+
305
+ }
306
+
307
+
308
+ if($post_result){
309
+ //update existing post
310
+ $post_data['ID'] = $post_result;
311
+ $post_id = wp_update_post($post_data);
312
+
313
+ //check for previous attachments
314
+ $atta_allimages =& get_children('post_type=attachment&post_parent=' . $post_id);
315
+ if (!empty($atta_allimages)) {
316
+ foreach ($atta_allimages as $image) {
317
+ wp_delete_attachment($image->ID);
318
+ }
319
+ }
320
+
321
+ } else {
322
+ if($post_data['mwp_post_edit'] && $post_data['mwp_force_publish']){
323
+ $post_id = wp_insert_post($post_data);
324
+ } elseif($post_data['mwp_post_edit'] && !$post_data['mwp_force_publish']) {
325
+ return array('error' => "Post not found.");
326
+ } else {
327
+ $post_id = wp_insert_post($post_data);
328
+ }
329
+
330
+ }
331
+
332
+ if (count($attachments)) {
333
+ foreach ($attachments as $atta_id => $featured_id) {
334
+ $result = wp_update_post(array(
335
+ 'ID' => $atta_id,
336
+ 'post_parent' => $post_id
337
+ ));
338
+ if ($featured_id > 0) {
339
+ $new_custom['_thumbnail_id'] = array(
340
+ $featured_id
341
+ );
342
+ }
343
+ }
344
+ }
345
+
346
+ // featured image
347
+ if ($post_featured_img != '') {
348
+ $file_name = basename($post_featured_img);
349
+ if(isset($upload['error']) && !empty($upload['error'])){
350
+ return array('error' => $upload['error']);
351
+ }
352
+ $tmp_file = download_url($post_featured_img);
353
+ if(is_wp_error($tmp_file)){
354
+ return array('error' => $tmp_file->get_error_message());
355
+ }
356
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
357
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
358
+ $renamed = @rename($tmp_file, $attach_upload['path']);
359
+ if ($renamed === true) {
360
+ $atta_ext = end(explode('.', $file_name));
361
+
362
+ $attachment = array(
363
+ 'post_title' => $file_name,
364
+ 'post_content' => '',
365
+ 'post_type' => 'attachment',
366
+ 'post_parent' => $post_id,
367
+ 'post_mime_type' => 'image/' . $atta_ext,
368
+ 'guid' => $attach_upload['url']
369
+ );
370
+
371
+ // Save the data
372
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
373
+ wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
374
+ $new_custom['_thumbnail_id'] = array(
375
+ $attach_id
376
+ );
377
+ } else {
378
+ @unlink($tmp_file);
379
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
380
+ }
381
+ @unlink($tmp_file);
382
+ }
383
+
384
+ if ($post_id && is_array($post_categories)) {
385
+ //insert categories
386
+
387
+ $cat_ids = wp_create_categories($post_categories, $post_id);
388
+ }
389
+
390
+
391
+ //get current custom fields
392
+ $cur_custom = get_post_custom($post_id);
393
+ //check which values doesnot exists in new custom fields
394
+ $diff_values = array_diff_key($cur_custom, $new_custom);
395
+
396
+ if (is_array($diff_values))
397
+ foreach ($diff_values as $meta_key => $value) {
398
+ delete_post_meta($post_id, $meta_key);
399
+ }
400
+ //insert new post meta
401
+ foreach ($new_custom as $meta_key => $value) {
402
+ if (strpos($meta_key, '_mmb') === 0 || strpos($meta_key, '_edit') === 0) {
403
+ continue;
404
+ } else {
405
+ update_post_meta($post_id, $meta_key, $value[0]);
406
+ }
407
+ }
408
+ return $post_id;
409
+ }
410
+
411
+
412
+ function change_status($args)
413
+ {
414
+
415
+ global $wpdb;
416
+ $post_id = $args['post_id'];
417
+ $status = $args['status'];
418
+ $success = false;
419
+
420
+ if(in_array($status, array('draft', 'publish', 'trash'))){
421
+ $sql = "update ".$wpdb->prefix."posts set post_status = '$status' where ID = '$post_id'";
422
+ $success = $wpdb->query($sql);
423
+ }
424
+
425
+ return $success;
426
+ }
427
+
428
+ /**
429
+ * Function which gets posts from worker depending on arguments.
430
+ * If FROM and TO dates are provided and range, range has bigger priority to date FROM.
431
+ * This means if there are less posts between FROM and TO than range provided,
432
+ * this function omit date from and returns last range number posts to date TO.
433
+ *
434
+ * @param array $args arguments passed to function
435
+ * @arg string filter_posts search phrase for post titles
436
+ * @arg string mwp_get_posts_date_from date in format(Y-m-d H:i:s) when posts are publishes from
437
+ * @arg string mwp_get_posts_date_to date in format(Y-m-d H:i:s) when posts are publishes to
438
+ * @arg string mwp_get_posts_range range number of returned posts
439
+ * @arg string mwp_get_posts_publish on or off
440
+ * @arg string mwp_get_posts_pending on or off
441
+ * @arg string mwp_get_posts_private on or off
442
+ * @arg string mwp_get_posts_future on or off
443
+ * @arg string mwp_get_posts_draft on or off
444
+ * @arg string mwp_get_posts_trash on or off
445
+ * @return array posts related to args
446
+ */
447
+ function get_posts($args){
448
+ global $wpdb;
449
+
450
+ $where='';
451
+
452
+ extract($args);
453
+
454
+ if(!empty($filter_posts))
455
+ {
456
+ $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_posts)."%'";
457
+ }
458
+
459
+ if(!empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
460
+ {
461
+ $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_posts_date_from)."' AND '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
462
+ }
463
+ else if(!empty($mwp_get_posts_date_from) && empty($mwp_get_posts_date_to))
464
+ {
465
+ $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_posts_date_from)."'";
466
+ }
467
+ else if(empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
468
+ {
469
+ $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
470
+ }
471
+ $post_array=array();
472
+ $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
473
+ foreach ($args as $checkbox => $checkbox_val)
474
+ {
475
+ if($checkbox_val=="on") {
476
+ $post_array[]="'".str_replace("mwp_get_posts_","",$checkbox)."'";
477
+ }
478
+ }
479
+ if(!empty($post_array))
480
+ {
481
+ $where.=" AND post_status IN (".implode(",",$post_array).")";
482
+ }
483
+
484
+ $limit = ($mwp_get_posts_range) ? ' LIMIT ' . mysql_real_escape_string($mwp_get_posts_range) : ' LIMIT 500';
485
+
486
+ $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' ".$where." ORDER BY post_date DESC";
487
+
488
+ $total = array();
489
  $posts = array();
490
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query.$limit);
491
+ $user_info = $this->getUsersIDs();
492
+ $post_cats=$this->getPostCats();
493
+ $post_tags=$this->getPostCats('post_tag');
494
+ $total['total_num']=count($posts_info);
495
+
496
+ if($mwp_get_posts_range && !empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to) && $total['total_num'] < $mwp_get_posts_range) {
497
+ $sql_query = "$wpdb->posts
498
+ WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'
499
+ ORDER BY post_date DESC
500
+ LIMIT " . mysql_real_escape_string($mwp_get_posts_range);
501
+
502
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query);
503
+ $total = array();
504
+ $total['total_num']=count($posts_info);
505
+ }
506
+
507
+ foreach ( $posts_info as $post_info )
508
+ {
509
+
510
+ $cats=array();
511
+ foreach($post_cats[$post_info->ID] as $cat_array => $cat_array_val)
512
+ {
513
+ $cats[] = array('name' => $cat_array_val);
514
+ }
515
+
516
+ $tags=array();
517
+ if (!empty($post_tags[$post_info->ID])) {
518
+ foreach($post_tags[$post_info->ID] as $tag_array => $tag_array_val)
519
+ {
520
+ $tags[] = array('name' => $tag_array_val);
521
+ }
522
+ }
523
+
524
+ $posts[]=array(
525
+ 'post_id'=>$post_info->ID,
526
+ 'post_title'=>$post_info->post_title,
527
+ 'post_name'=>$post_info->post_name,
528
+ 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
529
+ 'post_date'=>$post_info->post_date,
530
+ 'post_modified'=>$post_info->post_modified,
531
+ 'post_status'=>$post_info->post_status,
532
+ 'post_type'=>$post_info->post_type,
533
+ 'guid'=>$post_info->guid,
534
+ 'post_password'=>$post_info->post_password,
535
+ 'ping_status'=>$post_info->ping_status,
536
+ 'comment_status'=>$post_info->comment_status,
537
+ 'comment_count'=>$post_info->comment_count,
538
+ 'cats'=>$cats,
539
+ 'tags'=>$tags,
540
+
541
+ );
542
+ }
543
+
544
+ return array('posts' => $posts, 'total' => $total);
545
+ }
546
+
547
+ function delete_post($args){
548
+ global $wpdb;
549
+ if(!empty($args['post_id']) && !empty($args['action']))
550
+ {
551
+ if($args['action']=='delete')
552
+ {
553
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
554
+ }
555
+ else if($args['action']=='delete_perm'){
556
+ $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
557
+ }
558
+ else if($args['action']=='delete_restore'){
559
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
560
+ }
561
+ $wpdb->get_results($delete_query);
562
+
563
+ return 'Post deleted.';
564
+ }
565
+ else
566
+ {
567
+ return 'No ID...';
568
+ }
569
+ }
570
+
571
+ function delete_posts($args){
572
+ global $wpdb;
573
+ extract($args);
574
+ if($deleteaction=='delete'){
575
+ $delete_query_intro = "DELETE FROM $wpdb->posts WHERE ID = ";
576
+ }elseif($deleteaction=='trash'){
577
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ";
578
+ }elseif($deleteaction=='draft'){
579
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = ";
580
+ }elseif($deleteaction=='publish'){
581
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ";
582
+ }
583
+ foreach($args as $key=>$val){
584
+
585
+ if(!empty($val) && is_numeric($val))
586
+ {
587
+ $delete_query = $delete_query_intro.$val;
588
+
589
+ $wpdb->query($delete_query);
590
+ }
591
+ }
592
+ return "Post deleted";
593
+
594
+ }
595
+
596
+ /**
597
  * Function which gets pages from worker depending on arguments.
598
  * If FROM and TO dates are provided and range, range has bigger priority to date FROM.
599
  * This means if there are less pages between FROM and TO than range provided,
600
+ * this function omit date from and returns last range number pages to date TO.
601
+ *
602
+ * @param array $args arguments passed to function
603
+ * @arg string filter_pages search phrase for page titles
604
+ * @arg string mwp_get_pages_date_from date in format(Y-m-d H:i:s) when pages are publishes from
605
+ * @arg string mwp_get_pages_date_to date in format(Y-m-d H:i:s) when pages are publishes to
606
+ * @arg string mwp_get_pages_range range number of returned pages
607
+ * @arg string mwp_get_pages_publish on or off
608
+ * @arg string mwp_get_pages_pending on or off
609
+ * @arg string mwp_get_pages_private on or off
610
+ * @arg string mwp_get_pages_future on or off
611
+ * @arg string mwp_get_pages_draft on or off
612
+ * @arg string mwp_get_pages_trash on or off
613
  * @return array pages related to args
614
+ */
615
+ function get_pages($args){
616
+ global $wpdb;
617
+
618
+ $where='';
619
+ extract($args);
620
+
621
+ if(!empty($filter_pages))
622
+ {
623
+ $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_pages)."%'";
624
+ }
625
+ if(!empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
626
+ {
627
+ $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_pages_date_from)."' AND '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
628
+ }
629
+ else if(!empty($mwp_get_pages_date_from) && empty($mwp_get_pages_date_to))
630
+ {
631
+ $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_pages_date_from)."'";
632
+ }
633
+ else if(empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
634
+ {
635
+ $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
636
+ }
637
+
638
+ $post_array=array();
639
+ $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
640
+ foreach ($args as $checkbox => $checkbox_val)
641
+ {
642
+ if($checkbox_val=="on") {
643
+ $post_array[]="'".str_replace("mwp_get_pages_","",$checkbox)."'";
644
+ }
645
+ }
646
+ if(!empty($post_array))
647
+ {
648
+ $where.=" AND post_status IN (".implode(",",$post_array).")";
649
+ }
650
+
651
+ $limit = ($mwp_get_pages_range) ? ' LIMIT ' . mysql_real_escape_string($mwp_get_pages_range) : ' LIMIT 500';
652
+
653
+ $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='page' ".$where.' ORDER BY post_date DESC';
654
+
655
+ $total = array();
656
+ $posts = array();
657
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query.$limit);
658
+ $user_info = $this->getUsersIDs();
659
+ $total['total_num']=count($posts_info);
660
+
661
+ if($mwp_get_pages_range && !empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to) && $total['total_num'] < $mwp_get_pages_range) {
662
+ $sql_query = "$wpdb->posts
663
+ WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'
664
+ ORDER BY post_date DESC
665
+ LIMIT " . mysql_real_escape_string($mwp_get_pages_range);
666
+
667
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query);
668
+ $total = array();
669
+ $total['total_num']=count($posts_info);
670
+ }
671
+
672
+ foreach ( $posts_info as $post_info )
673
+ {
674
+
675
+ $posts[]=array(
676
+ 'post_id'=>$post_info->ID,
677
+ 'post_title'=>$post_info->post_title,
678
+ 'post_name'=>$post_info->post_name,
679
+ 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
680
+ 'post_date'=>$post_info->post_date,
681
+ 'post_modified'=>$post_info->post_modified,
682
+ 'post_status'=>$post_info->post_status,
683
+ 'post_type'=>$post_info->post_type,
684
+ 'guid'=>$post_info->guid,
685
+ 'post_password'=>$post_info->post_password,
686
+ 'ping_status'=>$post_info->ping_status,
687
+ 'comment_status'=>$post_info->comment_status,
688
+ 'comment_count'=>$post_info->comment_count
689
+
690
+ );
691
+ }
692
+
693
+ return array('posts' => $posts, 'total' => $total);
694
+ }
695
+
696
+ function delete_page($args){
697
+ global $wpdb;
698
+ if(!empty($args['post_id']) && !empty($args['action']))
699
+ {
700
+ if($args['action']=='delete')
701
+ {
702
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
703
+ }
704
+ else if($args['action']=='delete_perm'){
705
+ $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
706
+ }
707
+ else if($args['action']=='delete_restore'){
708
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
709
+ }
710
+ $wpdb->get_results($delete_query);
711
+
712
+ return 'Page deleted.';
713
+ }
714
+ else
715
+ {
716
+ return 'No ID...';
717
+ }
718
+ }
719
+
720
+ function getPostCats($taxonomy = 'category')
721
+ {
722
+ global $wpdb;
723
+
724
+ $cats = $wpdb->get_results("SELECT p.ID AS post_id, $wpdb->terms.name
725
+ FROM $wpdb->posts AS p
726
+ INNER JOIN $wpdb->term_relationships ON ( p.ID = $wpdb->term_relationships.object_id )
727
+ INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
728
+ AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
729
+ INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
730
+
731
+ foreach ( $cats as $post_val )
732
+ {
733
+
734
+ $post_cats[$post_val->post_id][] = $post_val->name;
735
+ }
736
+
737
+ return $post_cats;
738
+ }
739
+
740
+ function getUsersIDs()
741
+ {
742
+ global $wpdb;
743
+ $users_authors=array();
744
+ $users = $wpdb->get_results("SELECT ID as user_id, display_name FROM $wpdb->users WHERE user_status=0");
745
+
746
+ foreach ( $users as $user_key=>$user_val )
747
+ {
748
+ $users_authors[$user_val->user_id] = $user_val->display_name;
749
+ }
750
+
751
+ return $users_authors;
752
+ }
753
+ }
754
  ?>
readme.txt CHANGED
@@ -34,6 +34,18 @@ Check out [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs").
34
 
35
  == Changelog ==
36
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  = 3.9.22 =
38
  - New: Backup support for Google Drive
39
  - New: Keyword tracking limit increased from 5 to 20 times the website limit (ie. with 25 website account you can now track the ranking for 500 keywords!)
@@ -182,7 +194,7 @@ Check out [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs").
182
  = 3.8.8 =
183
  * New feature: Bulk add links to blogroll
184
  * New feature: Manual backups to email address
185
- * New feature: Backup requirements check (under �Manage Backups�)
186
  * New feature: Popup menu for groups allowing to show dashboard for that group only
187
  * New feature: Favorite list for plugins and themes for later quick installation to multiple blogs
188
  * New feature: Invite friends
34
 
35
  == Changelog ==
36
 
37
+ = 3.9.23 =
38
+ - New: SEO reports can be branded and viewed by sharing an URL
39
+ - New: Set custom database prefix for new clone destination
40
+ - New: Automatic change all URL paths for new clone destination
41
+ - New: Success and fail email notifications for scheduled backup tasks
42
+ - Fix: Improved scheduled backups for limited server resources
43
+ - Fix: Improved backup to Dropbox (now supporting larger backup files)
44
+ - Fix: Handling of external images with bulk posting
45
+ - Fix: Display plugin versions on manage plugins
46
+ - Fix: Deprecated get_themes function
47
+ - Fix: Special characters support for notes
48
+
49
  = 3.9.22 =
50
  - New: Backup support for Google Drive
51
  - New: Keyword tracking limit increased from 5 to 20 times the website limit (ie. with 25 website account you can now track the ranking for 500 keywords!)
194
  = 3.8.8 =
195
  * New feature: Bulk add links to blogroll
196
  * New feature: Manual backups to email address
197
+ * New feature: Backup requirements check (under �Manage Backups�)
198
  * New feature: Popup menu for groups allowing to show dashboard for that group only
199
  * New feature: Favorite list for plugins and themes for later quick installation to multiple blogs
200
  * New feature: Invite friends
version CHANGED
@@ -1 +1 @@
1
- 3.9.22
1
+ 3.9.23