ManageWP Worker - Version 3.9.28

Version Description

  • New: Control Wordpress Automatic Background Updates for plugins and themes!
  • Fix: Tweaks to SFTP support for backups and clone
  • Fix: Enhancements to Backup and Branding features
Download this release

Release Info

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

Code changes from version 3.9.27 to 3.9.28

Files changed (12) hide show
  1. backup.class.php +77 -46
  2. core.class.php +164 -117
  3. init.php +217 -5
  4. installer.class.php +398 -389
  5. lib/dropbox.php +3 -3
  6. lib/s3.php +2307 -1949
  7. plugins/cleanup/cleanup.php +64 -55
  8. readme.txt +7 -1
  9. security.class.php +440 -0
  10. stats.class.php +9 -0
  11. updater.php +266 -0
  12. version +1 -1
backup.class.php CHANGED
@@ -23,18 +23,18 @@ $zip_errors = array(
23
  'No error',
24
  'No error',
25
  'Unexpected end of zip file',
26
- 'A generic error in the zipfile format was detected.',
27
  'zip was unable to allocate itself memory',
28
  'A severe error in the zipfile format was detected',
29
  'Entry too large to be split with zipsplit',
30
  'Invalid comment format',
31
  'zip -T failed or out of memory',
32
  'The user aborted zip prematurely',
33
- 'zip encountered an error while using a temp file',
34
  'Read or seek error',
35
  'zip has nothing to do',
36
  'Missing or empty zip file',
37
- 'Error writing to a file',
38
  'zip was unable to create a file to write to',
39
  'bad command line parameters',
40
  'no error',
@@ -115,7 +115,7 @@ class MMB_Backup extends MMB_Core {
115
  */
116
  function set_memory() {
117
  $changed = array('execution_time' => 0, 'memory_limit' => 0);
118
-
119
  $memory_limit = trim(ini_get('memory_limit'));
120
  $last = strtolower(substr($memory_limit, -1));
121
 
@@ -131,8 +131,9 @@ class MMB_Backup extends MMB_Core {
131
  $changed['memory_limit'] = 1;
132
  }
133
 
134
- if ( (int) @ini_get('max_execution_time') < 600 ) {
135
- @set_time_limit(600); //ten minutes
 
136
  $changed['execution_time'] = 1;
137
  }
138
 
@@ -294,6 +295,11 @@ class MMB_Backup extends MMB_Core {
294
  //Update task with next schedule
295
  $this->set_backup_task($update);
296
 
 
 
 
 
 
297
  $result = $this->backup($setting['task_args'], $task_name);
298
  $error = '';
299
 
@@ -368,7 +374,7 @@ class MMB_Backup extends MMB_Core {
368
  $this->set_backup_task(array(
369
  'task_name' => $task_name,
370
  'args' => $settings[$task_name]['task_args'],
371
- 'error' => $result
372
  ));
373
  return $result;
374
  } else {
@@ -423,9 +429,8 @@ class MMB_Backup extends MMB_Core {
423
 
424
  if (!file_exists($new_file_path)) {
425
  if (!mkdir($new_file_path, 0755, true))
426
- $error_message = 'Permission denied, make sure you have write permission to wp-content folder.';
427
- return array(
428
- 'error' => $error_message
429
  );
430
  }
431
 
@@ -480,9 +485,9 @@ class MMB_Backup extends MMB_Core {
480
  $duration = round($end_compress - $begin_compress, 2);
481
 
482
  if ($size > 1000) {
483
- $paths['size'] = ceil($size / 1024) . "mb";
484
  } else {
485
- $paths['size'] = $size . 'kb';
486
  }
487
 
488
  $paths['duration'] = $duration . 's';
@@ -523,7 +528,7 @@ class MMB_Backup extends MMB_Core {
523
  }
524
 
525
  $temp = $backup_settings[$task_name]['task_results'];
526
- $temp = array_values($temp);
527
  $paths['time'] = time();
528
 
529
  if ($task_name != 'Backup Now') {
@@ -608,7 +613,9 @@ class MMB_Backup extends MMB_Core {
608
 
609
  $remove = array(
610
  trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
611
- trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
 
 
612
  );
613
  $exclude = array_merge($exclude, $remove);
614
 
@@ -661,6 +668,7 @@ class MMB_Backup extends MMB_Core {
661
  * @return bool is compress successful or not
662
  */
663
  function zip_backup_db($task_name, $backup_file) {
 
664
  $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
665
  $comp_level = $disable_comp ? '-0' : '-1';
666
  $zip = $this->get_zip();
@@ -716,9 +724,9 @@ class MMB_Backup extends MMB_Core {
716
  $zip = new PclZip($backup_file);
717
 
718
  if ($disable_comp) {
719
- $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
720
  } else {
721
- $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
722
  }
723
 
724
  return $result;
@@ -736,6 +744,7 @@ class MMB_Backup extends MMB_Core {
736
  */
737
  function zip_backup($task_name, $backup_file, $exclude, $include) {
738
  global $zip_errors;
 
739
  $sys = substr(PHP_OS, 0, 3);
740
 
741
  //Exclude paths
@@ -787,8 +796,10 @@ class MMB_Backup extends MMB_Core {
787
  }
788
 
789
  //Additional includes?
790
- if (!empty($include)) {
791
  foreach ($include as $data) {
 
 
792
  if ($data) {
793
  if ($sys == 'WIN')
794
  $include_data .= " $data/*.*";
@@ -1035,7 +1046,7 @@ class MMB_Backup extends MMB_Core {
1035
  if (!file_exists($db_folder)) {
1036
  if (!mkdir($db_folder, 0755, true))
1037
  return array(
1038
- 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
1039
  );
1040
  }
1041
 
@@ -1060,7 +1071,7 @@ class MMB_Backup extends MMB_Core {
1060
  $socketname = '';
1061
  if(strpos(DB_HOST,':')!==false)
1062
  {
1063
- $host_sock = split(':',DB_HOST);
1064
  $hostname = $host_sock[0];
1065
  $socketname = $host_sock[1];
1066
  $port = intval($host_sock[1]);
@@ -1202,6 +1213,7 @@ class MMB_Backup extends MMB_Core {
1202
  $what = 'full';
1203
  } else {
1204
  $tasks = $this->tasks;
 
1205
  $task = $tasks[$task_name];
1206
  if (isset($task['task_results'][$result_id]['server'])) {
1207
  $backup_file = $task['task_results'][$result_id]['server']['file_path'];
@@ -1479,8 +1491,26 @@ class MMB_Backup extends MMB_Core {
1479
  return array('error' => 'Cannot access database file.');
1480
  }
1481
 
1482
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1483
- $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1484
 
1485
  ob_start();
1486
  $result = $this->mmb_exec($command);
@@ -1488,9 +1518,8 @@ class MMB_Backup extends MMB_Core {
1488
  if (!$result) {
1489
  $this->_log('DB restore fallback to PHP');
1490
  //try php
1491
- $this->restore_db_php($file_name);
1492
  }
1493
-
1494
  @unlink($file_name);
1495
  return true;
1496
  }
@@ -1554,28 +1583,19 @@ class MMB_Backup extends MMB_Core {
1554
  *
1555
  * @return bool optimized successfully or not
1556
  */
1557
- function optimize_tables() {
 
1558
  global $wpdb;
1559
- $query = 'SHOW TABLES';
1560
- $tables = $wpdb->get_results($query, ARRAY_A);
 
1561
  foreach ($tables as $table) {
1562
- if (in_array($table['Engine'], array(
1563
- 'MyISAM',
1564
- 'ISAM',
1565
- 'HEAP',
1566
- 'MEMORY',
1567
- 'ARCHIVE'
1568
- )))
1569
- $table_string .= $table['Name'] . ",";
1570
- elseif ($table['Engine'] == 'InnoDB') {
1571
- $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1572
- }
1573
  }
1574
-
1575
- $table_string = rtrim($table_string);
1576
  $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1577
 
1578
- return $optimize ? true : false;
1579
 
1580
  }
1581
 
@@ -1606,8 +1626,13 @@ class MMB_Backup extends MMB_Core {
1606
  $paths['mysql'] = 'mysql'; // try anyway
1607
 
1608
  $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1609
- if (empty($paths['mysqldump']))
1610
  $paths['mysqldump'] = 'mysqldump'; // try anyway
 
 
 
 
 
1611
  }
1612
 
1613
  return $paths;
@@ -1866,7 +1891,7 @@ class MMB_Backup extends MMB_Core {
1866
  $sftp_password = $sftp_password?$sftp_password:"";
1867
  // file_put_contents("sftp_log.txt","sftp pass:".$sftp_password,FILE_APPEND);
1868
  // file_put_contents("sftp_log.txt","Creating NetSFTP",FILE_APPEND);
1869
- $sftp = new Net_SFTP($sftp_hostname);
1870
  // file_put_contents("sftp_log.txt","Created NetSFTP",FILE_APPEND);
1871
  $remote = $sftp_remote_folder ? trim($sftp_remote_folder,"/")."/" : '';
1872
  if (!$sftp->login($sftp_username, $sftp_password)) {
@@ -2044,7 +2069,7 @@ class MMB_Backup extends MMB_Core {
2044
  $sftp_hostname = $sftp_hostname?$sftp_hostname:"";
2045
  $sftp_username = $sftp_username?$sftp_username:"";
2046
  $sftp_password = $sftp_password?$sftp_password:"";
2047
- $sftp = new Net_SFTP($sftp_hostname);
2048
  if (!$sftp->login($sftp_username, $sftp_password)) {
2049
  file_put_contents("sftp_log.txt","sftp login failed in remove_sftp_backup",FILE_APPEND);
2050
  return false;
@@ -2128,7 +2153,7 @@ class MMB_Backup extends MMB_Core {
2128
  $sftp_username = $sftp_username?$sftp_username:"";
2129
  $sftp_password = $sftp_password?$sftp_password:"";
2130
  file_put_contents("sftp_log.txt","sftp host:".$sftp_hostname.";username:".$sftp_username.";password:".$sftp_password,FILE_APPEND);
2131
- $sftp = new Net_SFTP($sftp_hostname);
2132
  if (!$sftp->login($sftp_username, $sftp_password)) {
2133
  file_put_contents("sftp_log.txt","sftp login failed in get_sftp_backup",FILE_APPEND);
2134
  return false;
@@ -2984,11 +3009,13 @@ class MMB_Backup extends MMB_Core {
2984
  if (empty($args))
2985
  return false;
2986
  extract($args);
 
2987
  if (isset($google_drive_token)) {
2988
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
2989
  }
2990
 
2991
  $tasks = $this->tasks;
 
2992
  $task = $tasks[$task_name];
2993
  $backups = $task['task_results'];
2994
  $backup = $backups[$result_id];
@@ -3126,6 +3153,7 @@ class MMB_Backup extends MMB_Core {
3126
  extract($args);
3127
 
3128
  $tasks = $this->tasks;
 
3129
  $task = $tasks[$task_name];
3130
 
3131
  if (!empty($task)) {
@@ -3347,6 +3375,11 @@ class MMB_Backup extends MMB_Core {
3347
  @mysql_close($wpdb->dbh);
3348
  $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
3349
  wp_set_wpdb_vars();
 
 
 
 
 
3350
  }
3351
  }
3352
 
@@ -3492,5 +3525,3 @@ if (!function_exists('get_all_files_from_dir_recursive')) {
3492
  @closedir($dh);
3493
  }
3494
  }
3495
-
3496
- ?>
23
  'No error',
24
  'No error',
25
  'Unexpected end of zip file',
26
+ 'A generic error in the zipfile format was detected',
27
  'zip was unable to allocate itself memory',
28
  'A severe error in the zipfile format was detected',
29
  'Entry too large to be split with zipsplit',
30
  'Invalid comment format',
31
  'zip -T failed or out of memory',
32
  'The user aborted zip prematurely',
33
+ 'zip encountered an error while using a temp file. Please check if there is enough disk space',
34
  'Read or seek error',
35
  'zip has nothing to do',
36
  'Missing or empty zip file',
37
+ 'Error writing to a file. Please check if there is enough disk space',
38
  'zip was unable to create a file to write to',
39
  'bad command line parameters',
40
  'no error',
115
  */
116
  function set_memory() {
117
  $changed = array('execution_time' => 0, 'memory_limit' => 0);
118
+ @ignore_user_abort(true);
119
  $memory_limit = trim(ini_get('memory_limit'));
120
  $last = strtolower(substr($memory_limit, -1));
121
 
131
  $changed['memory_limit'] = 1;
132
  }
133
 
134
+ if ( (int) @ini_get('max_execution_time') < 4000 ) {
135
+ @ini_set('max_execution_time', 4000);
136
+ @set_time_limit(4000);
137
  $changed['execution_time'] = 1;
138
  }
139
 
295
  //Update task with next schedule
296
  $this->set_backup_task($update);
297
 
298
+ if($check == 'paused'){
299
+ continue;
300
+ }
301
+
302
+
303
  $result = $this->backup($setting['task_args'], $task_name);
304
  $error = '';
305
 
374
  $this->set_backup_task(array(
375
  'task_name' => $task_name,
376
  'args' => $settings[$task_name]['task_args'],
377
+ 'error' => $result['error']
378
  ));
379
  return $result;
380
  } else {
429
 
430
  if (!file_exists($new_file_path)) {
431
  if (!mkdir($new_file_path, 0755, true))
432
+ return array(
433
+ 'error' => 'Permission denied, make sure you have write permissions to the wp-content folder.'
 
434
  );
435
  }
436
 
485
  $duration = round($end_compress - $begin_compress, 2);
486
 
487
  if ($size > 1000) {
488
+ $paths['size'] = ceil($size / 1024) . "MB";
489
  } else {
490
+ $paths['size'] = $size . 'KB';
491
  }
492
 
493
  $paths['duration'] = $duration . 's';
528
  }
529
 
530
  $temp = $backup_settings[$task_name]['task_results'];
531
+ $temp = @array_values($temp);
532
  $paths['time'] = time();
533
 
534
  if ($task_name != 'Backup Now') {
613
 
614
  $remove = array(
615
  trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
616
+ trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups",
617
+ trim(basename(WP_CONTENT_DIR)) . "/cache",
618
+ trim(basename(WP_CONTENT_DIR)) . "/w3tc",
619
  );
620
  $exclude = array_merge($exclude, $remove);
621
 
668
  * @return bool is compress successful or not
669
  */
670
  function zip_backup_db($task_name, $backup_file) {
671
+ $backup_file = escapeshellarg($backup_file);
672
  $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
673
  $comp_level = $disable_comp ? '-0' : '-1';
674
  $zip = $this->get_zip();
724
  $zip = new PclZip($backup_file);
725
 
726
  if ($disable_comp) {
727
+ $result = $zip->add(MWP_BACKUP_DIR."/mwp_db/", PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
728
  } else {
729
+ $result = $zip->add(MWP_BACKUP_DIR."/mwp_db/", PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
730
  }
731
 
732
  return $result;
744
  */
745
  function zip_backup($task_name, $backup_file, $exclude, $include) {
746
  global $zip_errors;
747
+ $backup_file = escapeshellarg($backup_file);
748
  $sys = substr(PHP_OS, 0, 3);
749
 
750
  //Exclude paths
796
  }
797
 
798
  //Additional includes?
799
+ if (!empty($include) && is_array($include)) {
800
  foreach ($include as $data) {
801
+ if(empty($data))
802
+ continue;
803
  if ($data) {
804
  if ($sys == 'WIN')
805
  $include_data .= " $data/*.*";
1046
  if (!file_exists($db_folder)) {
1047
  if (!mkdir($db_folder, 0755, true))
1048
  return array(
1049
+ 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have correct write permissions.'
1050
  );
1051
  }
1052
 
1071
  $socketname = '';
1072
  if(strpos(DB_HOST,':')!==false)
1073
  {
1074
+ $host_sock = explode(':',DB_HOST);
1075
  $hostname = $host_sock[0];
1076
  $socketname = $host_sock[1];
1077
  $port = intval($host_sock[1]);
1213
  $what = 'full';
1214
  } else {
1215
  $tasks = $this->tasks;
1216
+ $task_name = stripslashes($task_name);
1217
  $task = $tasks[$task_name];
1218
  if (isset($task['task_results'][$result_id]['server'])) {
1219
  $backup_file = $task['task_results'][$result_id]['server']['file_path'];
1491
  return array('error' => 'Cannot access database file.');
1492
  }
1493
 
1494
+ $port = 0;
1495
+ $host = DB_HOST;
1496
+
1497
+ if (strpos($host, ':') !== false){
1498
+ list($host, $port) = explode(':', $host);
1499
+ }
1500
+ $socket = false;
1501
+
1502
+ if (strpos($host, '/') !== false || strpos($host, '\\') !== false) {
1503
+ $socket = true;
1504
+ }
1505
+
1506
+ if ($socket) {
1507
+ $connection = sprintf('--socket=%s', escapeshellarg($host));
1508
+ } else {
1509
+ $connection = sprintf('--host=%s --port=%s', escapeshellarg($host), escapeshellarg($port));
1510
+ }
1511
+
1512
+ $command = "%s %s --user=%s --password=%s --default-character-set=%s %s < %s";
1513
+ $command = sprintf($command, escapeshellarg($paths['mysql']), $connection, escapeshellarg(DB_USER), escapeshellarg(DB_PASSWORD), escapeshellarg('utf8'), escapeshellarg(DB_NAME), escapeshellarg($file_name));
1514
 
1515
  ob_start();
1516
  $result = $this->mmb_exec($command);
1518
  if (!$result) {
1519
  $this->_log('DB restore fallback to PHP');
1520
  //try php
1521
+ return $this->restore_db_php($file_name);
1522
  }
 
1523
  @unlink($file_name);
1524
  return true;
1525
  }
1583
  *
1584
  * @return bool optimized successfully or not
1585
  */
1586
+ function optimize_tables()
1587
+ {
1588
  global $wpdb;
1589
+ $query = 'SHOW TABLE STATUS';
1590
+ $tables = $wpdb->get_results($query, ARRAY_A);
1591
+ $table_string = '';
1592
  foreach ($tables as $table) {
1593
+ $table_string .= $table['Name'] . ",";
 
 
 
 
 
 
 
 
 
 
1594
  }
1595
+ $table_string = rtrim($table_string, ",");
 
1596
  $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1597
 
1598
+ return (bool)$optimize;
1599
 
1600
  }
1601
 
1626
  $paths['mysql'] = 'mysql'; // try anyway
1627
 
1628
  $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1629
+ if (empty($paths['mysqldump'])){
1630
  $paths['mysqldump'] = 'mysqldump'; // try anyway
1631
+ $baseDir = $wpdb->get_var('select @@basedir');
1632
+ if ($baseDir) {
1633
+ $paths['mysqldump'] = $baseDir.'/bin/mysqldump';
1634
+ }
1635
+ }
1636
  }
1637
 
1638
  return $paths;
1891
  $sftp_password = $sftp_password?$sftp_password:"";
1892
  // file_put_contents("sftp_log.txt","sftp pass:".$sftp_password,FILE_APPEND);
1893
  // file_put_contents("sftp_log.txt","Creating NetSFTP",FILE_APPEND);
1894
+ $sftp = new Net_SFTP($sftp_hostname,$port);
1895
  // file_put_contents("sftp_log.txt","Created NetSFTP",FILE_APPEND);
1896
  $remote = $sftp_remote_folder ? trim($sftp_remote_folder,"/")."/" : '';
1897
  if (!$sftp->login($sftp_username, $sftp_password)) {
2069
  $sftp_hostname = $sftp_hostname?$sftp_hostname:"";
2070
  $sftp_username = $sftp_username?$sftp_username:"";
2071
  $sftp_password = $sftp_password?$sftp_password:"";
2072
+ $sftp = new Net_SFTP($sftp_hostname,$port);
2073
  if (!$sftp->login($sftp_username, $sftp_password)) {
2074
  file_put_contents("sftp_log.txt","sftp login failed in remove_sftp_backup",FILE_APPEND);
2075
  return false;
2153
  $sftp_username = $sftp_username?$sftp_username:"";
2154
  $sftp_password = $sftp_password?$sftp_password:"";
2155
  file_put_contents("sftp_log.txt","sftp host:".$sftp_hostname.";username:".$sftp_username.";password:".$sftp_password,FILE_APPEND);
2156
+ $sftp = new Net_SFTP($sftp_hostname,$port);
2157
  if (!$sftp->login($sftp_username, $sftp_password)) {
2158
  file_put_contents("sftp_log.txt","sftp login failed in get_sftp_backup",FILE_APPEND);
2159
  return false;
3009
  if (empty($args))
3010
  return false;
3011
  extract($args);
3012
+ $task_name = stripslashes($task_name);
3013
  if (isset($google_drive_token)) {
3014
  $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
3015
  }
3016
 
3017
  $tasks = $this->tasks;
3018
+
3019
  $task = $tasks[$task_name];
3020
  $backups = $task['task_results'];
3021
  $backup = $backups[$result_id];
3153
  extract($args);
3154
 
3155
  $tasks = $this->tasks;
3156
+ $task_name = stripslashes($task_name);
3157
  $task = $tasks[$task_name];
3158
 
3159
  if (!empty($task)) {
3375
  @mysql_close($wpdb->dbh);
3376
  $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
3377
  wp_set_wpdb_vars();
3378
+ if (function_exists('is_multisite')) {
3379
+ if (is_multisite()) {
3380
+ $wpdb->set_blog_id(get_current_blog_id());
3381
+ }
3382
+ }
3383
  }
3384
  }
3385
 
3525
  @closedir($dh);
3526
  }
3527
  }
 
 
core.class.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  /*************************************************************
3
- *
4
  * core.class.php
5
- *
6
  * Upgrade Plugins
7
- *
8
- *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
@@ -27,6 +27,7 @@ class MMB_Core extends MMB_Helper
27
  var $search_instance;
28
  var $links_instance;
29
  var $user_instance;
 
30
  var $backup_instance;
31
  var $installer_instance;
32
  var $mmb_multisite;
@@ -36,20 +37,20 @@ class MMB_Core extends MMB_Helper
36
  private $mmb_pre_init_actions;
37
  private $mmb_pre_init_filters;
38
  private $mmb_init_actions;
39
-
40
-
41
  function __construct()
42
  {
43
  global $mmb_plugin_dir, $wpmu_version, $blog_id, $_mmb_plugin_actions, $_mmb_item_filter, $_mmb_options;
44
-
45
  $_mmb_plugin_actions = array();
46
  $_mmb_options = get_option('wrksettings');
47
  $_mmb_options = !empty($_mmb_options) ? $_mmb_options : array();
48
-
49
  $this->name = 'Manage Multiple Blogs';
50
  $this->action_call = null;
51
  $this->action_params = null;
52
-
53
  if ( function_exists('is_multisite') ) {
54
  if ( is_multisite() ) {
55
  $this->mmb_multisite = $blog_id;
@@ -62,7 +63,7 @@ class MMB_Core extends MMB_Helper
62
  $this->mmb_multisite = false;
63
  $this->network_admin_install = null;
64
  }
65
-
66
  // admin notices
67
  if ( !get_option('_worker_public_key') ){
68
  if( $this->mmb_multisite ){
@@ -77,18 +78,18 @@ class MMB_Core extends MMB_Helper
77
  add_action('admin_notices', array( &$this, 'admin_notice' ));
78
  }
79
  }
80
-
81
  // default filters
82
  //$this->mmb_pre_init_filters['get_stats']['mmb_stats_filter'][] = array('MMB_Stats', 'pre_init_stats'); // called with class name, use global $mmb_core inside the function instead of $this
83
  $this->mmb_pre_init_filters['get_stats']['mmb_stats_filter'][] = 'mmb_pre_init_stats';
84
-
85
  $_mmb_item_filter['pre_init_stats'] = array( 'core_update', 'hit_counter', 'comments', 'backups', 'posts', 'drafts', 'scheduled' );
86
  $_mmb_item_filter['get'] = array( 'updates', 'errors' );
87
-
88
  $this->mmb_pre_init_actions = array(
89
  'backup_req' => 'mmb_get_backup_req',
90
  );
91
-
92
  $this->mmb_init_actions = array(
93
  'do_upgrade' => 'mmb_do_upgrade',
94
  'get_stats' => 'mmb_stats_get',
@@ -122,7 +123,7 @@ class MMB_Core extends MMB_Helper
122
  'set_notifications' => 'mmb_set_notifications',
123
  'clean_orphan_backups' => 'mmb_clean_orphan_backups',
124
  'get_users' => 'mmb_get_users',
125
- 'edit_users' => 'mmb_edit_users',
126
  'get_posts' => 'mmb_get_posts',
127
  'delete_post' => 'mmb_delete_post',
128
  'delete_posts' => 'mmb_delete_posts',
@@ -134,8 +135,21 @@ class MMB_Core extends MMB_Helper
134
  'worker_brand' => 'mmb_worker_brand',
135
  'maintenance' => 'mmb_maintenance_mode',
136
  'get_dbname' => 'mmb_get_dbname',
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  );
138
-
139
  $mwp_worker_brand = get_option("mwp_worker_brand");
140
  //!$mwp_worker_brand['hide_managed_remotely']
141
  if ($mwp_worker_brand == false || (is_array($mwp_worker_brand) && !array_key_exists('hide_managed_remotely', $mwp_worker_brand))) {
@@ -151,39 +165,41 @@ class MMB_Core extends MMB_Helper
151
  }
152
  add_action( 'plugins_loaded', array( &$this, 'dissalow_text_editor' ) );
153
 
154
- add_action('admin_init', array(&$this,'admin_actions'));
155
  add_action('init', array( &$this, 'mmb_remote_action'), 9999);
156
  add_action('setup_theme', 'mmb_run_backup_action', 1);
157
  add_action('plugins_loaded', 'mmb_authenticate', 1);
158
  add_action('setup_theme', 'mmb_parse_request');
159
  add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
160
  add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
 
 
161
  }
162
-
163
  function mmb_remote_action(){
164
  if($this->action_call != null){
165
  $params = isset($this->action_params) && $this->action_params != null ? $this->action_params : array();
166
  call_user_func($this->action_call, $params);
167
  }
168
  }
169
-
170
  function register_action_params( $action = false, $params = array() ){
171
-
172
  if(isset($this->mmb_pre_init_actions[$action]) && function_exists($this->mmb_pre_init_actions[$action])){
173
  call_user_func($this->mmb_pre_init_actions[$action], $params);
174
  }
175
-
176
  if(isset($this->mmb_init_actions[$action]) && function_exists($this->mmb_init_actions[$action])){
177
  $this->action_call = $this->mmb_init_actions[$action];
178
  $this->action_params = $params;
179
-
180
  if( isset($this->mmb_pre_init_filters[$action]) && !empty($this->mmb_pre_init_filters[$action])){
181
  global $mmb_filters;
182
-
183
  foreach($this->mmb_pre_init_filters[$action] as $_name => $_functions){
184
  if(!empty($_functions)){
185
  $data = array();
186
-
187
  foreach($_functions as $_k => $_callback){
188
  if(is_array($_callback) && method_exists($_callback[0], $_callback[1]) ){
189
  $data = call_user_func( $_callback, $params );
@@ -194,41 +210,56 @@ class MMB_Core extends MMB_Helper
194
  add_filter( $_name, create_function( '$a' , 'global $mmb_filters; return array_merge($a, $mmb_filters["'.$_name.'"]);') );
195
  }
196
  }
197
-
198
  }
199
  }
200
  return true;
201
- }
202
  return false;
203
  }
204
-
205
  /**
206
- * Add notice to network admin dashboard for security reasons
207
- *
208
  */
209
  function network_admin_notice()
210
  {
211
- echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
212
- Please add this site and your network blogs, with your network adminstrator username, to your <a target="_blank" href="http://managewp.com/wp-admin">ManageWP.com</a> account now to remove this notice or "Network Deactivate" the Worker plugin to avoid <a target="_blank" href="http://managewp.com/user-guide/security">security issues</a>.
 
 
 
 
 
213
  </p></div>';
214
  }
215
-
216
-
217
  /**
218
- * Add notice to admin dashboard for security reasons
219
- *
220
  */
221
  function admin_notice()
222
  {
223
- echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
224
- Please add this site now to your <a target="_blank" href="http://managewp.com/wp-admin">ManageWP.com</a> account. Or deactivate the Worker plugin to avoid <a target="_blank" href="http://managewp.com/user-guide/security">security issues</a>.
 
 
 
 
 
 
 
 
 
 
225
  </p></div>';
226
  }
227
-
228
  /**
229
- * Add an item into the Right Now Dashboard widget
230
  * to inform that the blog can be managed remotely
231
- *
232
  */
233
  function add_right_now_info()
234
  {
@@ -328,6 +359,9 @@ EOF;
328
  </form>
329
  <div id="support_response_id" style="margin-top: 14px"></div>
330
  <style>
 
 
 
331
  .ui-widget-overlay {
332
  background-repeat: repeat;
333
  }
@@ -425,7 +459,7 @@ EOF;
425
 
426
  /**
427
  * Get parent blog options
428
- *
429
  */
430
  private function get_parent_blog_option( $option_name = '' )
431
  {
@@ -433,104 +467,117 @@ EOF;
433
  $option = $wpdb->get_var( $wpdb->prepare( "SELECT `option_value` FROM {$wpdb->base_prefix}options WHERE option_name = %s LIMIT 1", $option_name ) );
434
  return $option;
435
  }
436
-
437
  /**
438
  * Gets an instance of the Comment class
439
- *
440
  */
441
  function get_comment_instance()
442
  {
443
  if (!isset($this->comment_instance)) {
444
  $this->comment_instance = new MMB_Comment();
445
  }
446
-
447
  return $this->comment_instance;
448
  }
449
-
450
  /**
451
  * Gets an instance of the Plugin class
452
- *
453
  */
454
  function get_plugin_instance()
455
  {
456
  if (!isset($this->plugin_instance)) {
457
  $this->plugin_instance = new MMB_Plugin();
458
  }
459
-
460
  return $this->plugin_instance;
461
  }
462
-
463
  /**
464
  * Gets an instance of the Theme class
465
- *
466
  */
467
  function get_theme_instance()
468
  {
469
  if (!isset($this->theme_instance)) {
470
  $this->theme_instance = new MMB_Theme();
471
  }
472
-
473
  return $this->theme_instance;
474
  }
475
-
476
-
477
  /**
478
  * Gets an instance of MMB_Post class
479
- *
480
  */
481
  function get_post_instance()
482
  {
483
  if (!isset($this->post_instance)) {
484
  $this->post_instance = new MMB_Post();
485
  }
486
-
487
  return $this->post_instance;
488
  }
489
-
490
  /**
491
  * Gets an instance of Blogroll class
492
- *
493
  */
494
  function get_blogroll_instance()
495
  {
496
  if (!isset($this->blogroll_instance)) {
497
  $this->blogroll_instance = new MMB_Blogroll();
498
  }
499
-
500
  return $this->blogroll_instance;
501
  }
502
-
503
-
504
-
505
  /**
506
  * Gets an instance of the WP class
507
- *
508
  */
509
  function get_wp_instance()
510
  {
511
  if (!isset($this->wp_instance)) {
512
  $this->wp_instance = new MMB_WP();
513
  }
514
-
515
  return $this->wp_instance;
516
  }
517
-
518
  /**
519
  * Gets an instance of User
520
- *
521
  */
522
  function get_user_instance()
523
  {
524
  if (!isset($this->user_instance)) {
525
  $this->user_instance = new MMB_User();
526
  }
527
-
528
  return $this->user_instance;
529
  }
 
 
 
 
 
 
 
 
 
 
 
 
530
 
 
531
  /**
532
  * Gets an instance of stats class
533
- *
534
  */
535
  function get_stats_instance()
536
  {
@@ -541,7 +588,7 @@ EOF;
541
  }
542
  /**
543
  * Gets an instance of search class
544
- *
545
  */
546
  function get_search_instance()
547
  {
@@ -560,10 +607,10 @@ EOF;
560
  if (!isset($this->backup_instance)) {
561
  $this->backup_instance = new MMB_Backup();
562
  }
563
-
564
  return $this->backup_instance;
565
  }
566
-
567
  /**
568
  * Gets an instance of links class
569
  *
@@ -573,10 +620,10 @@ EOF;
573
  if (!isset($this->link_instance)) {
574
  $this->link_instance = new MMB_Link();
575
  }
576
-
577
  return $this->link_instance;
578
  }
579
-
580
  function get_installer_instance()
581
  {
582
  if (!isset($this->installer_instance)) {
@@ -584,16 +631,16 @@ EOF;
584
  }
585
  return $this->installer_instance;
586
  }
587
-
588
  /**
589
  * Plugin install callback function
590
  * Check PHP version
591
  */
592
  function install() {
593
-
594
  global $wpdb, $_wp_using_ext_object_cache, $current_user;
595
  $_wp_using_ext_object_cache = false;
596
-
597
  //delete plugin options, just in case
598
  if ($this->mmb_multisite != false) {
599
  $network_blogs = $wpdb->get_results("select `blog_id`, `site_id` from `{$wpdb->blogs}`");
@@ -603,9 +650,9 @@ EOF;
603
  foreach($network_blogs as $details){
604
  if($details->site_id == $details->blog_id)
605
  update_blog_option($details->blog_id, 'mmb_network_admin_install', 1);
606
- else
607
  update_blog_option($details->blog_id, 'mmb_network_admin_install', -1);
608
-
609
  delete_blog_option($blog_id, '_worker_nossl_key');
610
  delete_blog_option($blog_id, '_worker_public_key');
611
  delete_blog_option($blog_id, '_action_message_id');
@@ -622,33 +669,33 @@ EOF;
622
  delete_option('_worker_public_key');
623
  delete_option('_action_message_id');
624
  }
625
-
626
  //delete_option('mwp_backup_tasks');
627
  delete_option('mwp_notifications');
628
  delete_option('mwp_worker_brand');
629
  delete_option('mwp_pageview_alerts');
630
  }
631
-
632
  /**
633
  * Saves the (modified) options into the database
634
- *
635
  */
636
  function save_options( $options = array() ){
637
  global $_mmb_options;
638
-
639
  $_mmb_options = array_merge( $_mmb_options, $options );
640
  update_option('wrksettings', $options);
641
  }
642
-
643
  /**
644
  * Deletes options for communication with master
645
- *
646
  */
647
  function uninstall( $deactivate = false )
648
  {
649
  global $current_user, $wpdb, $_wp_using_ext_object_cache;
650
  $_wp_using_ext_object_cache = false;
651
-
652
  if ($this->mmb_multisite != false) {
653
  $network_blogs = $wpdb->get_col("select `blog_id` from `{$wpdb->blogs}`");
654
  if(!empty($network_blogs)){
@@ -671,7 +718,7 @@ EOF;
671
  } else {
672
  if( $deactivate )
673
  delete_option('mmb_network_admin_install');
674
-
675
  delete_option('_worker_nossl_key');
676
  delete_option('_worker_public_key');
677
  delete_option('_action_message_id');
@@ -682,7 +729,7 @@ EOF;
682
  delete_option('_worker_public_key');
683
  delete_option('_action_message_id');
684
  }
685
-
686
  //Delete options
687
  delete_option('mwp_maintenace_mode');
688
  //delete_option('mwp_backup_tasks');
@@ -693,11 +740,11 @@ EOF;
693
  wp_clear_scheduled_hook('mwp_notifications');
694
  wp_clear_scheduled_hook('mwp_datasend');
695
  }
696
-
697
-
698
  /**
699
  * Constructs a url (for ajax purpose)
700
- *
701
  * @param mixed $base_page
702
  */
703
  function construct_url($params = array(), $base_page = 'index.php')
@@ -706,13 +753,13 @@ EOF;
706
  foreach ($params as $key => $value) {
707
  $url .= "&$key=$value";
708
  }
709
-
710
  return $url;
711
  }
712
-
713
  /**
714
  * Worker update
715
- *
716
  */
717
  function update_worker_plugin($params)
718
  {
@@ -723,13 +770,13 @@ EOF;
723
  @include_once ABSPATH . 'wp-admin/includes/template.php';
724
  @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
725
  @include_once ABSPATH . 'wp-admin/includes/screen.php';
726
-
727
  if (!$this->is_server_writable()) {
728
  return array(
729
  'error' => 'Failed, please <a target="_blank" href="http://managewp.com/user-guide/faq/my-pluginsthemes-fail-to-update-or-i-receive-a-yellow-ftp-warning">add FTP details for automatic upgrades.</a>'
730
  );
731
  }
732
-
733
  ob_start();
734
  @unlink(dirname(__FILE__));
735
  $upgrader = new Plugin_Upgrader();
@@ -757,43 +804,43 @@ EOF;
757
  'error' => 'Bad download path for worker installation file.'
758
  );
759
  }
760
-
761
  /**
762
  * Automatically logs in when called from Master
763
- *
764
  */
765
  function automatic_login()
766
  {
767
  $where = isset($_GET['mwp_goto']) ? $_GET['mwp_goto'] : false;
768
  $username = isset($_GET['username']) ? $_GET['username'] : '';
769
  $auto_login = isset($_GET['auto_login']) ? $_GET['auto_login'] : 0;
770
-
771
  if( !function_exists('is_user_logged_in') )
772
  include_once( ABSPATH.'wp-includes/pluggable.php' );
773
-
774
  if (( $auto_login && strlen(trim($username)) && !is_user_logged_in() ) || (isset($this->mmb_multisite) && $this->mmb_multisite )) {
775
  $signature = base64_decode($_GET['signature']);
776
  $message_id = trim($_GET['message_id']);
777
-
778
  $auth = $this->authenticate_message($where . $message_id, $signature, $message_id);
779
  if ($auth === true) {
780
-
781
  if (!headers_sent())
782
  header('P3P: CP="CAO PSA OUR"');
783
-
784
  if(!defined('MMB_USER_LOGIN'))
785
  define('MMB_USER_LOGIN', true);
786
-
787
  $siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
788
  $user = $this->mmb_get_user_info($username);
789
  wp_set_current_user($user->ID);
790
-
791
  if(!defined('COOKIEHASH') || (isset($this->mmb_multisite) && $this->mmb_multisite) )
792
  wp_cookie_constants();
793
-
794
  wp_set_auth_cookie($user->ID);
795
  @mmb_worker_header();
796
-
797
  if((isset($this->mmb_multisite) && $this->mmb_multisite ) || isset($_REQUEST['mwpredirect'])){
798
  if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
799
  wp_safe_redirect(admin_url($where));
@@ -813,31 +860,31 @@ EOF;
813
  }
814
  }
815
  }
816
-
817
  function mmb_set_auth_cookie( $auth_cookie ){
818
  if(!defined('MMB_USER_LOGIN'))
819
  return false;
820
-
821
  if( !defined('COOKIEHASH') )
822
  wp_cookie_constants();
823
-
824
  $_COOKIE['wordpress_'.COOKIEHASH] = $auth_cookie;
825
-
826
  }
827
  function mmb_set_logged_in_cookie( $logged_in_cookie ){
828
  if(!defined('MMB_USER_LOGIN'))
829
  return false;
830
-
831
  if( !defined('COOKIEHASH') )
832
  wp_cookie_constants();
833
-
834
  $_COOKIE['wordpress_logged_in_'.COOKIEHASH] = $logged_in_cookie;
835
  }
836
-
837
  function admin_actions(){
838
  add_filter('all_plugins', array($this, 'worker_replace'));
839
  }
840
-
841
  function worker_replace($all_plugins){
842
  $replace = get_option("mwp_worker_brand");
843
  if(is_array($replace)){
@@ -850,7 +897,7 @@ EOF;
850
  $all_plugins['worker/init.php']['AuthorName'] = $replace['author'];
851
  $all_plugins['worker/init.php']['PluginURI'] = '';
852
  }
853
-
854
  if($replace['hide']){
855
  if (!function_exists('get_plugins')) {
856
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
@@ -859,13 +906,13 @@ EOF;
859
  if (!$activated_plugins)
860
  $activated_plugins = array();
861
  if(in_array('worker/init.php',$activated_plugins))
862
- unset($all_plugins['worker/init.php']);
863
  }
864
  }
865
-
866
-
867
  return $all_plugins;
868
  }
869
-
870
  }
871
  ?>
1
  <?php
2
  /*************************************************************
3
+ *
4
  * core.class.php
5
+ *
6
  * Upgrade Plugins
7
+ *
8
+ *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
27
  var $search_instance;
28
  var $links_instance;
29
  var $user_instance;
30
+ var $security_instance;
31
  var $backup_instance;
32
  var $installer_instance;
33
  var $mmb_multisite;
37
  private $mmb_pre_init_actions;
38
  private $mmb_pre_init_filters;
39
  private $mmb_init_actions;
40
+
41
+
42
  function __construct()
43
  {
44
  global $mmb_plugin_dir, $wpmu_version, $blog_id, $_mmb_plugin_actions, $_mmb_item_filter, $_mmb_options;
45
+
46
  $_mmb_plugin_actions = array();
47
  $_mmb_options = get_option('wrksettings');
48
  $_mmb_options = !empty($_mmb_options) ? $_mmb_options : array();
49
+
50
  $this->name = 'Manage Multiple Blogs';
51
  $this->action_call = null;
52
  $this->action_params = null;
53
+
54
  if ( function_exists('is_multisite') ) {
55
  if ( is_multisite() ) {
56
  $this->mmb_multisite = $blog_id;
63
  $this->mmb_multisite = false;
64
  $this->network_admin_install = null;
65
  }
66
+
67
  // admin notices
68
  if ( !get_option('_worker_public_key') ){
69
  if( $this->mmb_multisite ){
78
  add_action('admin_notices', array( &$this, 'admin_notice' ));
79
  }
80
  }
81
+
82
  // default filters
83
  //$this->mmb_pre_init_filters['get_stats']['mmb_stats_filter'][] = array('MMB_Stats', 'pre_init_stats'); // called with class name, use global $mmb_core inside the function instead of $this
84
  $this->mmb_pre_init_filters['get_stats']['mmb_stats_filter'][] = 'mmb_pre_init_stats';
85
+
86
  $_mmb_item_filter['pre_init_stats'] = array( 'core_update', 'hit_counter', 'comments', 'backups', 'posts', 'drafts', 'scheduled' );
87
  $_mmb_item_filter['get'] = array( 'updates', 'errors' );
88
+
89
  $this->mmb_pre_init_actions = array(
90
  'backup_req' => 'mmb_get_backup_req',
91
  );
92
+
93
  $this->mmb_init_actions = array(
94
  'do_upgrade' => 'mmb_do_upgrade',
95
  'get_stats' => 'mmb_stats_get',
123
  'set_notifications' => 'mmb_set_notifications',
124
  'clean_orphan_backups' => 'mmb_clean_orphan_backups',
125
  'get_users' => 'mmb_get_users',
126
+ 'edit_users' => 'mmb_edit_users',
127
  'get_posts' => 'mmb_get_posts',
128
  'delete_post' => 'mmb_delete_post',
129
  'delete_posts' => 'mmb_delete_posts',
135
  'worker_brand' => 'mmb_worker_brand',
136
  'maintenance' => 'mmb_maintenance_mode',
137
  'get_dbname' => 'mmb_get_dbname',
138
+ 'security_check' => 'mbb_security_check',
139
+ 'security_fix_folder_listing'=> 'mbb_security_fix_folder_listing',
140
+ 'security_fix_php_reporting'=> 'mbb_security_fix_php_reporting',
141
+ 'security_fix_database_reporting'=> 'mbb_security_fix_database_reporting',
142
+ 'security_fix_wp_version'=> 'mbb_security_fix_wp_version',
143
+ 'security_fix_admin_username'=>'mbb_security_fix_admin_username',
144
+ 'security_fix_htaccess_permission'=>'mbb_security_fix_htaccess_permission',
145
+ 'security_fix_scripts_styles'=>'mbb_security_fix_scripts_styles',
146
+ 'security_fix_file_permission'=>'mbb_security_fix_file_permission',
147
+ 'security_fix_all' =>'mbb_security_fix_all',
148
+ 'get_autoupdate_plugins_themes' => 'mmb_get_autoupdate_plugins_themes',
149
+ 'edit_autoupdate_plugins_themes' => 'mmb_edit_autoupdate_plugins_themes',
150
+
151
  );
152
+
153
  $mwp_worker_brand = get_option("mwp_worker_brand");
154
  //!$mwp_worker_brand['hide_managed_remotely']
155
  if ($mwp_worker_brand == false || (is_array($mwp_worker_brand) && !array_key_exists('hide_managed_remotely', $mwp_worker_brand))) {
165
  }
166
  add_action( 'plugins_loaded', array( &$this, 'dissalow_text_editor' ) );
167
 
168
+ add_action('admin_init', array(&$this,'admin_actions'));
169
  add_action('init', array( &$this, 'mmb_remote_action'), 9999);
170
  add_action('setup_theme', 'mmb_run_backup_action', 1);
171
  add_action('plugins_loaded', 'mmb_authenticate', 1);
172
  add_action('setup_theme', 'mmb_parse_request');
173
  add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
174
  add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
175
+
176
+
177
  }
178
+
179
  function mmb_remote_action(){
180
  if($this->action_call != null){
181
  $params = isset($this->action_params) && $this->action_params != null ? $this->action_params : array();
182
  call_user_func($this->action_call, $params);
183
  }
184
  }
185
+
186
  function register_action_params( $action = false, $params = array() ){
187
+
188
  if(isset($this->mmb_pre_init_actions[$action]) && function_exists($this->mmb_pre_init_actions[$action])){
189
  call_user_func($this->mmb_pre_init_actions[$action], $params);
190
  }
191
+
192
  if(isset($this->mmb_init_actions[$action]) && function_exists($this->mmb_init_actions[$action])){
193
  $this->action_call = $this->mmb_init_actions[$action];
194
  $this->action_params = $params;
195
+
196
  if( isset($this->mmb_pre_init_filters[$action]) && !empty($this->mmb_pre_init_filters[$action])){
197
  global $mmb_filters;
198
+
199
  foreach($this->mmb_pre_init_filters[$action] as $_name => $_functions){
200
  if(!empty($_functions)){
201
  $data = array();
202
+
203
  foreach($_functions as $_k => $_callback){
204
  if(is_array($_callback) && method_exists($_callback[0], $_callback[1]) ){
205
  $data = call_user_func( $_callback, $params );
210
  add_filter( $_name, create_function( '$a' , 'global $mmb_filters; return array_merge($a, $mmb_filters["'.$_name.'"]);') );
211
  }
212
  }
213
+
214
  }
215
  }
216
  return true;
217
+ }
218
  return false;
219
  }
220
+
221
  /**
222
+ * Add notice to network admin dashboard for security reasons
223
+ *
224
  */
225
  function network_admin_notice()
226
  {
227
+ global $status, $page, $s;
228
+ $context = $status;
229
+ $plugin = 'worker/init.php';
230
+ $nonce = wp_create_nonce('deactivate-plugin_' . $plugin);
231
+ $actions = 'plugins.php?action=deactivate&amp;plugin='.urlencode($plugin).'&amp;plugin_status=' . $context . '&amp;paged=' . $page.'&amp;s=' . $s. '&amp;_wpnonce=' .$nonce ;
232
+ echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">ManageWP Notice</p><p>
233
+ Please <a href="https://managewp.com" target="_blank">add this site and your network blogs</a>, with your network administrator username, to your ManageWP account. <a target="_blank" href="https://managewp.com/features">What is ManageWP?</a> <br ><br > Otherwise, click to <a href="'.$actions.'">deactivate ManageWP plugin</a></em>.
234
  </p></div>';
235
  }
236
+
237
+
238
  /**
239
+ * Add notice to admin dashboard for security reasons
240
+ *
241
  */
242
  function admin_notice()
243
  {
244
+ global $status, $page, $s;
245
+ $context = $status;
246
+ $plugin = 'worker/init.php';
247
+ $nonce = wp_create_nonce('deactivate-plugin_' . $plugin);
248
+ $actions = 'plugins.php?action=deactivate&amp;plugin='.urlencode($plugin).'&amp;plugin_status=' . $context . '&amp;paged=' . $page.'&amp;s=' . $s. '&amp;_wpnonce=' .$nonce ;
249
+ $deactivation = 'click to <a href="'.$actions.'">deactivate ManageWP plugin</a>';
250
+ if($this->mmb_multisite && $this->network_admin_install != '1'){
251
+ $deactivation = "deactivate ManageWP plugin";
252
+ }
253
+ echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">ManageWP Notice</p><p>
254
+ Please <a href="https://managewp.com" target="_blank">add this site</a> to your ManageWP account. <a target="_blank" href="https://managewp.com/features">What is ManageWP?</a> <br ><br >
255
+ <em>Otherwise, '.$deactivation.'</em>.
256
  </p></div>';
257
  }
258
+
259
  /**
260
+ * Add an item into the Right Now Dashboard widget
261
  * to inform that the blog can be managed remotely
262
+ *
263
  */
264
  function add_right_now_info()
265
  {
359
  </form>
360
  <div id="support_response_id" style="margin-top: 14px"></div>
361
  <style>
362
+ .ui-widget-content{
363
+ z-index: 300002;
364
+ }
365
  .ui-widget-overlay {
366
  background-repeat: repeat;
367
  }
459
 
460
  /**
461
  * Get parent blog options
462
+ *
463
  */
464
  private function get_parent_blog_option( $option_name = '' )
465
  {
467
  $option = $wpdb->get_var( $wpdb->prepare( "SELECT `option_value` FROM {$wpdb->base_prefix}options WHERE option_name = %s LIMIT 1", $option_name ) );
468
  return $option;
469
  }
470
+
471
  /**
472
  * Gets an instance of the Comment class
473
+ *
474
  */
475
  function get_comment_instance()
476
  {
477
  if (!isset($this->comment_instance)) {
478
  $this->comment_instance = new MMB_Comment();
479
  }
480
+
481
  return $this->comment_instance;
482
  }
483
+
484
  /**
485
  * Gets an instance of the Plugin class
486
+ *
487
  */
488
  function get_plugin_instance()
489
  {
490
  if (!isset($this->plugin_instance)) {
491
  $this->plugin_instance = new MMB_Plugin();
492
  }
493
+
494
  return $this->plugin_instance;
495
  }
496
+
497
  /**
498
  * Gets an instance of the Theme class
499
+ *
500
  */
501
  function get_theme_instance()
502
  {
503
  if (!isset($this->theme_instance)) {
504
  $this->theme_instance = new MMB_Theme();
505
  }
506
+
507
  return $this->theme_instance;
508
  }
509
+
510
+
511
  /**
512
  * Gets an instance of MMB_Post class
513
+ *
514
  */
515
  function get_post_instance()
516
  {
517
  if (!isset($this->post_instance)) {
518
  $this->post_instance = new MMB_Post();
519
  }
520
+
521
  return $this->post_instance;
522
  }
523
+
524
  /**
525
  * Gets an instance of Blogroll class
526
+ *
527
  */
528
  function get_blogroll_instance()
529
  {
530
  if (!isset($this->blogroll_instance)) {
531
  $this->blogroll_instance = new MMB_Blogroll();
532
  }
533
+
534
  return $this->blogroll_instance;
535
  }
536
+
537
+
538
+
539
  /**
540
  * Gets an instance of the WP class
541
+ *
542
  */
543
  function get_wp_instance()
544
  {
545
  if (!isset($this->wp_instance)) {
546
  $this->wp_instance = new MMB_WP();
547
  }
548
+
549
  return $this->wp_instance;
550
  }
551
+
552
  /**
553
  * Gets an instance of User
554
+ *
555
  */
556
  function get_user_instance()
557
  {
558
  if (!isset($this->user_instance)) {
559
  $this->user_instance = new MMB_User();
560
  }
561
+
562
  return $this->user_instance;
563
  }
564
+ /**
565
+ * Gets an instance of Security
566
+ *
567
+ */
568
+ function get_security_instance()
569
+ {
570
+ if (!isset($this->security_instance)) {
571
+ $this->security_instance = new MMB_Security();
572
+ }
573
+
574
+ return $this->security_instance;
575
+ }
576
 
577
+
578
  /**
579
  * Gets an instance of stats class
580
+ *
581
  */
582
  function get_stats_instance()
583
  {
588
  }
589
  /**
590
  * Gets an instance of search class
591
+ *
592
  */
593
  function get_search_instance()
594
  {
607
  if (!isset($this->backup_instance)) {
608
  $this->backup_instance = new MMB_Backup();
609
  }
610
+
611
  return $this->backup_instance;
612
  }
613
+
614
  /**
615
  * Gets an instance of links class
616
  *
620
  if (!isset($this->link_instance)) {
621
  $this->link_instance = new MMB_Link();
622
  }
623
+
624
  return $this->link_instance;
625
  }
626
+
627
  function get_installer_instance()
628
  {
629
  if (!isset($this->installer_instance)) {
631
  }
632
  return $this->installer_instance;
633
  }
634
+
635
  /**
636
  * Plugin install callback function
637
  * Check PHP version
638
  */
639
  function install() {
640
+
641
  global $wpdb, $_wp_using_ext_object_cache, $current_user;
642
  $_wp_using_ext_object_cache = false;
643
+
644
  //delete plugin options, just in case
645
  if ($this->mmb_multisite != false) {
646
  $network_blogs = $wpdb->get_results("select `blog_id`, `site_id` from `{$wpdb->blogs}`");
650
  foreach($network_blogs as $details){
651
  if($details->site_id == $details->blog_id)
652
  update_blog_option($details->blog_id, 'mmb_network_admin_install', 1);
653
+ else
654
  update_blog_option($details->blog_id, 'mmb_network_admin_install', -1);
655
+
656
  delete_blog_option($blog_id, '_worker_nossl_key');
657
  delete_blog_option($blog_id, '_worker_public_key');
658
  delete_blog_option($blog_id, '_action_message_id');
669
  delete_option('_worker_public_key');
670
  delete_option('_action_message_id');
671
  }
672
+
673
  //delete_option('mwp_backup_tasks');
674
  delete_option('mwp_notifications');
675
  delete_option('mwp_worker_brand');
676
  delete_option('mwp_pageview_alerts');
677
  }
678
+
679
  /**
680
  * Saves the (modified) options into the database
681
+ *
682
  */
683
  function save_options( $options = array() ){
684
  global $_mmb_options;
685
+
686
  $_mmb_options = array_merge( $_mmb_options, $options );
687
  update_option('wrksettings', $options);
688
  }
689
+
690
  /**
691
  * Deletes options for communication with master
692
+ *
693
  */
694
  function uninstall( $deactivate = false )
695
  {
696
  global $current_user, $wpdb, $_wp_using_ext_object_cache;
697
  $_wp_using_ext_object_cache = false;
698
+
699
  if ($this->mmb_multisite != false) {
700
  $network_blogs = $wpdb->get_col("select `blog_id` from `{$wpdb->blogs}`");
701
  if(!empty($network_blogs)){
718
  } else {
719
  if( $deactivate )
720
  delete_option('mmb_network_admin_install');
721
+
722
  delete_option('_worker_nossl_key');
723
  delete_option('_worker_public_key');
724
  delete_option('_action_message_id');
729
  delete_option('_worker_public_key');
730
  delete_option('_action_message_id');
731
  }
732
+
733
  //Delete options
734
  delete_option('mwp_maintenace_mode');
735
  //delete_option('mwp_backup_tasks');
740
  wp_clear_scheduled_hook('mwp_notifications');
741
  wp_clear_scheduled_hook('mwp_datasend');
742
  }
743
+
744
+
745
  /**
746
  * Constructs a url (for ajax purpose)
747
+ *
748
  * @param mixed $base_page
749
  */
750
  function construct_url($params = array(), $base_page = 'index.php')
753
  foreach ($params as $key => $value) {
754
  $url .= "&$key=$value";
755
  }
756
+
757
  return $url;
758
  }
759
+
760
  /**
761
  * Worker update
762
+ *
763
  */
764
  function update_worker_plugin($params)
765
  {
770
  @include_once ABSPATH . 'wp-admin/includes/template.php';
771
  @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
772
  @include_once ABSPATH . 'wp-admin/includes/screen.php';
773
+
774
  if (!$this->is_server_writable()) {
775
  return array(
776
  'error' => 'Failed, please <a target="_blank" href="http://managewp.com/user-guide/faq/my-pluginsthemes-fail-to-update-or-i-receive-a-yellow-ftp-warning">add FTP details for automatic upgrades.</a>'
777
  );
778
  }
779
+
780
  ob_start();
781
  @unlink(dirname(__FILE__));
782
  $upgrader = new Plugin_Upgrader();
804
  'error' => 'Bad download path for worker installation file.'
805
  );
806
  }
807
+
808
  /**
809
  * Automatically logs in when called from Master
810
+ *
811
  */
812
  function automatic_login()
813
  {
814
  $where = isset($_GET['mwp_goto']) ? $_GET['mwp_goto'] : false;
815
  $username = isset($_GET['username']) ? $_GET['username'] : '';
816
  $auto_login = isset($_GET['auto_login']) ? $_GET['auto_login'] : 0;
817
+
818
  if( !function_exists('is_user_logged_in') )
819
  include_once( ABSPATH.'wp-includes/pluggable.php' );
820
+
821
  if (( $auto_login && strlen(trim($username)) && !is_user_logged_in() ) || (isset($this->mmb_multisite) && $this->mmb_multisite )) {
822
  $signature = base64_decode($_GET['signature']);
823
  $message_id = trim($_GET['message_id']);
824
+
825
  $auth = $this->authenticate_message($where . $message_id, $signature, $message_id);
826
  if ($auth === true) {
827
+
828
  if (!headers_sent())
829
  header('P3P: CP="CAO PSA OUR"');
830
+
831
  if(!defined('MMB_USER_LOGIN'))
832
  define('MMB_USER_LOGIN', true);
833
+
834
  $siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
835
  $user = $this->mmb_get_user_info($username);
836
  wp_set_current_user($user->ID);
837
+
838
  if(!defined('COOKIEHASH') || (isset($this->mmb_multisite) && $this->mmb_multisite) )
839
  wp_cookie_constants();
840
+
841
  wp_set_auth_cookie($user->ID);
842
  @mmb_worker_header();
843
+
844
  if((isset($this->mmb_multisite) && $this->mmb_multisite ) || isset($_REQUEST['mwpredirect'])){
845
  if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
846
  wp_safe_redirect(admin_url($where));
860
  }
861
  }
862
  }
863
+
864
  function mmb_set_auth_cookie( $auth_cookie ){
865
  if(!defined('MMB_USER_LOGIN'))
866
  return false;
867
+
868
  if( !defined('COOKIEHASH') )
869
  wp_cookie_constants();
870
+
871
  $_COOKIE['wordpress_'.COOKIEHASH] = $auth_cookie;
872
+
873
  }
874
  function mmb_set_logged_in_cookie( $logged_in_cookie ){
875
  if(!defined('MMB_USER_LOGIN'))
876
  return false;
877
+
878
  if( !defined('COOKIEHASH') )
879
  wp_cookie_constants();
880
+
881
  $_COOKIE['wordpress_logged_in_'.COOKIEHASH] = $logged_in_cookie;
882
  }
883
+
884
  function admin_actions(){
885
  add_filter('all_plugins', array($this, 'worker_replace'));
886
  }
887
+
888
  function worker_replace($all_plugins){
889
  $replace = get_option("mwp_worker_brand");
890
  if(is_array($replace)){
897
  $all_plugins['worker/init.php']['AuthorName'] = $replace['author'];
898
  $all_plugins['worker/init.php']['PluginURI'] = '';
899
  }
900
+
901
  if($replace['hide']){
902
  if (!function_exists('get_plugins')) {
903
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
906
  if (!$activated_plugins)
907
  $activated_plugins = array();
908
  if(in_array('worker/init.php',$activated_plugins))
909
+ unset($all_plugins['worker/init.php']);
910
  }
911
  }
912
+
913
+
914
  return $all_plugins;
915
  }
916
+
917
  }
918
  ?>
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: ManageWP - Worker
4
  Plugin URI: http://managewp.com/
5
  Description: Manage Multiple WordPress sites from one dashboard. Visit <a href="https://managewp.com">ManageWP.com</a> to sign up.
6
  Author: ManageWP
7
- Version: 3.9.27
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.27');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
@@ -32,7 +32,6 @@ global $wpdb, $mmb_plugin_dir, $mmb_plugin_url, $wp_version, $mmb_filters, $_mmb
32
  if (version_compare(PHP_VERSION, '5.0.0', '<')) // min version 5 supported
33
  exit("<p>ManageWP Worker plugin requires PHP 5 or higher.</p>");
34
 
35
-
36
  $mmb_wp_version = $wp_version;
37
  $mmb_plugin_dir = WP_PLUGIN_DIR . '/' . basename(dirname(__FILE__));
38
  $mmb_plugin_url = WP_PLUGIN_URL . '/' . basename(dirname(__FILE__));
@@ -46,6 +45,7 @@ require_once("$mmb_plugin_dir/backup.class.php");
46
  require_once("$mmb_plugin_dir/installer.class.php");
47
  require_once("$mmb_plugin_dir/link.class.php");
48
  require_once("$mmb_plugin_dir/user.class.php");
 
49
  require_once("$mmb_plugin_dir/api.php");
50
 
51
  require_once("$mmb_plugin_dir/plugins/search/search.php");
@@ -141,6 +141,7 @@ if( !function_exists('mmb_authenticate')) {
141
 
142
  if($_mwp_data['action'] === 'add_site') {
143
  $_mwp_auth = true;
 
144
  } else {
145
  $_mwp_auth = $mmb_core->authenticate_message($_mwp_data['action'] . $_mwp_data['id'], $_mwp_data['signature'], $_mwp_data['id']);
146
  }
@@ -152,7 +153,11 @@ if( !function_exists('mmb_authenticate')) {
152
  if(isset($_mwp_data['params']['username']) && !is_user_logged_in()){
153
  $user = function_exists('get_user_by') ? get_user_by('login', $_mwp_data['params']['username']) : get_userdatabylogin( $_mwp_data['params']['username'] );
154
  wp_set_current_user($user->ID);
 
 
155
  }
 
 
156
  }
157
  }
158
 
@@ -165,7 +170,7 @@ if( !function_exists ( 'mmb_parse_request' )) {
165
  }
166
  ob_start();
167
  $_wp_using_ext_object_cache = false;
168
- @set_time_limit(600);
169
 
170
  if ($_mwp_data['action'] === 'add_site') {
171
  mmb_add_site($_mwp_data['params']);
@@ -913,6 +918,163 @@ if( !function_exists ( 'mmb_add_user' )) {
913
  }
914
  }
915
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
916
  if( !function_exists ('mmb_get_users')) {
917
  function mmb_get_users($params)
918
  {
@@ -990,6 +1152,8 @@ if( !function_exists ('mmb_delete_posts')) {
990
  }
991
  }
992
 
 
 
993
  if( !function_exists ('mmb_edit_posts')) {
994
  function mmb_edit_posts($params)
995
  {
@@ -1104,7 +1268,6 @@ if( !function_exists('mwp_check_backup_tasks') ){
1104
  function mwp_check_backup_tasks() {
1105
  global $mmb_core, $_wp_using_ext_object_cache;
1106
  $_wp_using_ext_object_cache = false;
1107
-
1108
  $mmb_core->get_backup_instance();
1109
  $mmb_core->backup_instance->check_backup_tasks();
1110
  }
@@ -1157,6 +1320,14 @@ if( !function_exists('mmb_get_plugins_themes') ){
1157
  }
1158
  }
1159
 
 
 
 
 
 
 
 
 
1160
  if( !function_exists('mmb_edit_plugins_themes') ){
1161
  function mmb_edit_plugins_themes($params) {
1162
  global $mmb_core;
@@ -1166,6 +1337,13 @@ if( !function_exists('mmb_edit_plugins_themes') ){
1166
  }
1167
  }
1168
 
 
 
 
 
 
 
 
1169
  if( !function_exists('mmb_worker_brand')){
1170
  function mmb_worker_brand($params) {
1171
  update_option("mwp_worker_brand",$params['brand']);
@@ -1249,6 +1427,9 @@ $mmb_core = new MMB_Core();
1249
  if(isset($_GET['auto_login']))
1250
  $mmb_core->automatic_login();
1251
 
 
 
 
1252
  if (function_exists('register_activation_hook'))
1253
  register_activation_hook( __FILE__ , array( $mmb_core, 'install' ));
1254
 
@@ -1306,3 +1487,34 @@ if (get_option('mwp_debug_enable')) {
1306
  set_error_handler('mwp_error_handler');
1307
  register_shutdown_function('mwp_fatal_error_handler');
1308
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  Plugin URI: http://managewp.com/
5
  Description: Manage Multiple WordPress sites from one dashboard. Visit <a href="https://managewp.com">ManageWP.com</a> to sign up.
6
  Author: ManageWP
7
+ Version: 3.9.28
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.28');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
32
  if (version_compare(PHP_VERSION, '5.0.0', '<')) // min version 5 supported
33
  exit("<p>ManageWP Worker plugin requires PHP 5 or higher.</p>");
34
 
 
35
  $mmb_wp_version = $wp_version;
36
  $mmb_plugin_dir = WP_PLUGIN_DIR . '/' . basename(dirname(__FILE__));
37
  $mmb_plugin_url = WP_PLUGIN_URL . '/' . basename(dirname(__FILE__));
45
  require_once("$mmb_plugin_dir/installer.class.php");
46
  require_once("$mmb_plugin_dir/link.class.php");
47
  require_once("$mmb_plugin_dir/user.class.php");
48
+ require_once("$mmb_plugin_dir/security.class.php");
49
  require_once("$mmb_plugin_dir/api.php");
50
 
51
  require_once("$mmb_plugin_dir/plugins/search/search.php");
141
 
142
  if($_mwp_data['action'] === 'add_site') {
143
  $_mwp_auth = true;
144
+ return;
145
  } else {
146
  $_mwp_auth = $mmb_core->authenticate_message($_mwp_data['action'] . $_mwp_data['id'], $_mwp_data['signature'], $_mwp_data['id']);
147
  }
153
  if(isset($_mwp_data['params']['username']) && !is_user_logged_in()){
154
  $user = function_exists('get_user_by') ? get_user_by('login', $_mwp_data['params']['username']) : get_userdatabylogin( $_mwp_data['params']['username'] );
155
  wp_set_current_user($user->ID);
156
+ if(@getenv('IS_WPE'))
157
+ wp_set_auth_cookie($user->ID);
158
  }
159
+ if(!defined("WP_ADMIN"))
160
+ define(WP_ADMIN,true);
161
  }
162
  }
163
 
170
  }
171
  ob_start();
172
  $_wp_using_ext_object_cache = false;
173
+ @set_time_limit(1200);
174
 
175
  if ($_mwp_data['action'] === 'add_site') {
176
  mmb_add_site($_mwp_data['params']);
918
  }
919
  }
920
 
921
+ if( !function_exists ( 'mbb_security_check' )) {
922
+ function mbb_security_check($params)
923
+ {
924
+ global $mmb_core;
925
+ $mmb_core->get_security_instance();
926
+ $return = $mmb_core->security_instance->security_check($params);
927
+ if (is_array($return) && array_key_exists('error', $return))
928
+ mmb_response($return['error'], false);
929
+ else {
930
+ mmb_response($return, true);
931
+ }
932
+
933
+ }
934
+ }
935
+
936
+ if( !function_exists ( 'mbb_security_fix_folder_listing' )) {
937
+ function mbb_security_fix_folder_listing($params)
938
+ {
939
+ global $mmb_core;
940
+ $mmb_core->get_security_instance();
941
+ $return = $mmb_core->security_instance->security_fix_dir_listing($params);
942
+ if (is_array($return) && array_key_exists('error', $return))
943
+ mmb_response($return['error'], false);
944
+ else {
945
+ mmb_response($return, true);
946
+ }
947
+
948
+ }
949
+ }
950
+
951
+ if( !function_exists ( 'mbb_security_fix_php_reporting' )) {
952
+ function mbb_security_fix_php_reporting($params)
953
+ {
954
+ global $mmb_core;
955
+ $mmb_core->get_security_instance();
956
+ $return = $mmb_core->security_instance->security_fix_php_reporting($params);
957
+ if (is_array($return) && array_key_exists('error', $return))
958
+ mmb_response($return['error'], false);
959
+ else {
960
+ mmb_response($return, true);
961
+ }
962
+
963
+ }
964
+ }
965
+
966
+ if( !function_exists ( 'mbb_security_fix_database_reporting' )) {
967
+ function mbb_security_fix_database_reporting($params)
968
+ {
969
+ global $mmb_core;
970
+ $mmb_core->get_security_instance();
971
+ $return = $mmb_core->security_instance->security_fix_database_reporting($params);
972
+ if (is_array($return) && array_key_exists('error', $return))
973
+ mmb_response($return['error'], false);
974
+ else {
975
+ mmb_response($return, true);
976
+ }
977
+
978
+ }
979
+ }
980
+
981
+ //security_fix_wp_version
982
+
983
+ if( !function_exists ( 'mbb_security_fix_wp_version' )) {
984
+ function mbb_security_fix_wp_version($params)
985
+ {
986
+ global $mmb_core;
987
+ $mmb_core->get_security_instance();
988
+ $return = $mmb_core->security_instance->security_fix_wp_version($params);
989
+ if (is_array($return) && array_key_exists('error', $return))
990
+ mmb_response($return['error'], false);
991
+ else {
992
+ mmb_response($return, true);
993
+ }
994
+
995
+ }
996
+ }
997
+
998
+ //mbb_security_fix_admin_username
999
+
1000
+ if( !function_exists ( 'mbb_security_fix_admin_username' )) {
1001
+ function mbb_security_fix_admin_username($params)
1002
+ {
1003
+ global $mmb_core;
1004
+ $mmb_core->get_security_instance();
1005
+ $return = $mmb_core->security_instance->security_fix_admin_username($params);
1006
+ if (is_array($return) && array_key_exists('error', $return))
1007
+ mmb_response($return['error'], false);
1008
+ else {
1009
+ mmb_response($return, true);
1010
+ }
1011
+
1012
+ }
1013
+ }
1014
+
1015
+ if( !function_exists ( 'mbb_security_fix_scripts_styles' )) {
1016
+ function mbb_security_fix_scripts_styles($params)
1017
+ {
1018
+ global $mmb_core;
1019
+ $mmb_core->get_security_instance();
1020
+ $return = $mmb_core->security_instance->security_fix_scripts_styles($params);
1021
+ if (is_array($return) && array_key_exists('error', $return))
1022
+ mmb_response($return['error'], false);
1023
+ else {
1024
+ mmb_response($return, true);
1025
+ }
1026
+
1027
+ }
1028
+ }
1029
+
1030
+ //mbb_security_fix_file_permission
1031
+ if( !function_exists ( 'mbb_security_fix_file_permission' )) {
1032
+ function mbb_security_fix_file_permission($params)
1033
+ {
1034
+ global $mmb_core;
1035
+ $mmb_core->get_security_instance();
1036
+ $return = $mmb_core->security_instance->security_fix_permissions($params);
1037
+ if (is_array($return) && array_key_exists('error', $return))
1038
+ mmb_response($return['error'], false);
1039
+ else {
1040
+ mmb_response($return, true);
1041
+ }
1042
+
1043
+ }
1044
+ }
1045
+
1046
+ //mbb_security_fix_all
1047
+ if( !function_exists ( 'mbb_security_fix_all' )) {
1048
+ function mbb_security_fix_all($params)
1049
+ {
1050
+ global $mmb_core;
1051
+ $mmb_core->get_security_instance();
1052
+ $return = $mmb_core->security_instance->security_fix_all($params);
1053
+ if (is_array($return) && array_key_exists('error', $return))
1054
+ mmb_response($return['error'], false);
1055
+ else {
1056
+ mmb_response($return, true);
1057
+ }
1058
+ }
1059
+ }
1060
+
1061
+ //mbb_security_fix_htaccess_permission
1062
+
1063
+ if( !function_exists ( 'mbb_security_fix_htaccess_permission' )) {
1064
+ function mbb_security_fix_htaccess_permission($params)
1065
+ {
1066
+ global $mmb_core;
1067
+ $mmb_core->get_security_instance();
1068
+ $return = $mmb_core->security_instance->security_fix_htaccess_permission($params);
1069
+ if (is_array($return) && array_key_exists('error', $return))
1070
+ mmb_response($return['error'], false);
1071
+ else {
1072
+ mmb_response($return, true);
1073
+ }
1074
+
1075
+ }
1076
+ }
1077
+
1078
  if( !function_exists ('mmb_get_users')) {
1079
  function mmb_get_users($params)
1080
  {
1152
  }
1153
  }
1154
 
1155
+
1156
+
1157
  if( !function_exists ('mmb_edit_posts')) {
1158
  function mmb_edit_posts($params)
1159
  {
1268
  function mwp_check_backup_tasks() {
1269
  global $mmb_core, $_wp_using_ext_object_cache;
1270
  $_wp_using_ext_object_cache = false;
 
1271
  $mmb_core->get_backup_instance();
1272
  $mmb_core->backup_instance->check_backup_tasks();
1273
  }
1320
  }
1321
  }
1322
 
1323
+
1324
+ if( !function_exists('mmb_get_autoupdate_plugins_themes') ){
1325
+ function mmb_get_autoupdate_plugins_themes($params) {
1326
+ $return = MWP_Updater::getSettings($params);
1327
+ mmb_response($return, true);
1328
+ }
1329
+ }
1330
+
1331
  if( !function_exists('mmb_edit_plugins_themes') ){
1332
  function mmb_edit_plugins_themes($params) {
1333
  global $mmb_core;
1337
  }
1338
  }
1339
 
1340
+ if( !function_exists('mmb_edit_autoupdate_plugins_themes') ){
1341
+ function mmb_edit_autoupdate_plugins_themes($params) {
1342
+ $return = MWP_Updater::setSettings($params);
1343
+ mmb_response($return, true);
1344
+ }
1345
+ }
1346
+
1347
  if( !function_exists('mmb_worker_brand')){
1348
  function mmb_worker_brand($params) {
1349
  update_option("mwp_worker_brand",$params['brand']);
1427
  if(isset($_GET['auto_login']))
1428
  $mmb_core->automatic_login();
1429
 
1430
+ require_once dirname(__FILE__) . '/updater.php';
1431
+ MWP_Updater::register();
1432
+
1433
  if (function_exists('register_activation_hook'))
1434
  register_activation_hook( __FILE__ , array( $mmb_core, 'install' ));
1435
 
1487
  set_error_handler('mwp_error_handler');
1488
  register_shutdown_function('mwp_fatal_error_handler');
1489
  }
1490
+
1491
+ if (get_option('mwp_remove_php_reporting') == 'T')
1492
+ {
1493
+ @error_reporting(0);
1494
+ @ini_set('display_errors', 'off');
1495
+ @ini_set('display_startup_errors', "off");
1496
+ }
1497
+
1498
+ if (get_option('mwp_remove_wp_version') == 'T')
1499
+ {
1500
+ remove_action('wp_head', 'wp_generator');
1501
+ remove_filter('wp_head', 'wp_generator');
1502
+ }
1503
+ if (get_option('managewp_remove_styles_version') == 'T')
1504
+ {
1505
+ global $wp_styles;
1506
+ if (!is_a($wp_styles, 'WP_Styles'))
1507
+ return;
1508
+
1509
+ foreach ($wp_styles->registered as $handle => $style)
1510
+ $wp_styles->registered[$handle]->ver = null;
1511
+ }
1512
+ if (get_option('managewp_remove_scripts_version') == 'T')
1513
+ {
1514
+ global $wp_scripts;
1515
+ if (!is_a($wp_scripts, 'WP_Scripts'))
1516
+ return;
1517
+
1518
+ foreach ($wp_scripts->registered as $handle => $script)
1519
+ $wp_scripts->registered[$handle]->ver = null;
1520
+ }
installer.class.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  /*************************************************************
3
- *
4
  * installer.class.php
5
- *
6
  * Upgrade WordPress
7
- *
8
- *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
@@ -24,18 +24,18 @@ class MMB_Installer extends MMB_Core
24
  @include_once(ABSPATH . 'wp-admin/includes/misc.php');
25
  @include_once(ABSPATH . 'wp-admin/includes/template.php');
26
  @include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
27
-
28
  global $wp_filesystem;
29
  if (!$wp_filesystem)
30
  WP_Filesystem();
31
  }
32
-
33
  function mmb_maintenance_mode($enable = false, $maintenance_message = '')
34
  {
35
  global $wp_filesystem;
36
-
37
  $maintenance_message .= '<?php $upgrading = ' . time() . '; ?>';
38
-
39
  $file = $wp_filesystem->abspath() . '.maintenance';
40
  if ($enable) {
41
  $wp_filesystem->delete($file);
@@ -44,32 +44,38 @@ class MMB_Installer extends MMB_Core
44
  $wp_filesystem->delete($file);
45
  }
46
  }
47
-
48
  function install_remote_file($params)
49
  {
50
  global $wp_filesystem;
51
  extract($params);
52
-
53
  if (!isset($package) || empty($package))
54
  return array(
55
  'error' => '<p>No files received. Internal error.</p>'
56
  );
57
-
 
 
 
 
 
 
58
  if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
59
  return array(
60
  'error' => '<p>Site under maintanace.</p>'
61
  );
62
-
63
  if (!class_exists('WP_Upgrader'))
64
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
65
-
66
  $upgrader_skin = new WP_Upgrader_Skin();
67
  $upgrader_skin->done_header = true;
68
-
69
  $upgrader = new WP_Upgrader($upgrader_skin);
70
  $destination = $type == 'themes' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR;
71
  $clear_destination = isset($clear_destination) ? $clear_destination : false;
72
-
73
  foreach ($package as $package_url) {
74
  $key = basename($package_url);
75
  $install_info[$key] = @$upgrader->run(array(
@@ -80,7 +86,7 @@ class MMB_Installer extends MMB_Core
80
  'hook_extra' => array()
81
  ));
82
  }
83
-
84
  if ($activate) {
85
  if ($type == 'plugins') {
86
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
@@ -98,67 +104,69 @@ class MMB_Installer extends MMB_Core
98
  } else if (count($install_info) == 1) {
99
  global $wp_themes;
100
  include_once(ABSPATH . 'wp-includes/theme.php');
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();
132
  $this->mmb_maintenance_mode(false);
133
  return $install_info;
134
  }
135
-
136
  function do_upgrade($params = null)
137
  {
138
- if ($params == null || empty($params))
 
 
139
  return array(
140
- 'failed' => 'No upgrades passed.'
141
  );
142
-
143
  if (!$this->is_server_writable()) {
144
  return array(
145
  'error' => 'Failed, please <a target="_blank" href="http://managewp.com/user-guide/faq/my-pluginsthemes-fail-to-update-or-i-receive-a-yellow-ftp-warning">add FTP details</a>'
146
  );
147
  }
148
-
149
-
150
  $params = isset($params['upgrades_all']) ? $params['upgrades_all'] : $params;
151
-
152
  $core_upgrade = isset($params['wp_upgrade']) ? $params['wp_upgrade'] : array();
153
  $upgrade_plugins = isset($params['upgrade_plugins']) ? $params['upgrade_plugins'] : array();
154
  $upgrade_themes = isset($params['upgrade_themes']) ? $params['upgrade_themes'] : array();
155
-
156
  $upgrades = array();
157
  $premium_upgrades = array();
158
  if (!empty($core_upgrade)) {
159
  $upgrades['core'] = $this->upgrade_core($core_upgrade);
160
  }
161
-
162
  if (!empty($upgrade_plugins)) {
163
  $plugin_files = array();
164
  foreach ($upgrade_plugins as $plugin) {
@@ -169,9 +177,9 @@ class MMB_Installer extends MMB_Core
169
  }
170
  if (!empty($plugin_files))
171
  $upgrades['plugins'] = $this->upgrade_plugins($plugin_files);
172
-
173
  }
174
-
175
  if (!empty($upgrade_themes)) {
176
  $theme_temps = array();
177
  foreach ($upgrade_themes as $theme) {
@@ -180,12 +188,12 @@ class MMB_Installer extends MMB_Core
180
  else
181
  $premium_upgrades[md5($theme['name'])] = $theme;
182
  }
183
-
184
  if (!empty($theme_temps))
185
  $upgrades['themes'] = $this->upgrade_themes($theme_temps);
186
-
187
  }
188
-
189
  if (!empty($premium_upgrades)) {
190
  $premium_upgrades = $this->upgrade_premium($premium_upgrades);
191
  if (!empty($premium_upgrades)) {
@@ -204,7 +212,7 @@ class MMB_Installer extends MMB_Core
204
  $this->mmb_maintenance_mode(false);
205
  return $upgrades;
206
  }
207
-
208
  /**
209
  * Upgrades WordPress locally
210
  *
@@ -212,16 +220,17 @@ class MMB_Installer extends MMB_Core
212
  function upgrade_core($current)
213
  {
214
  ob_start();
215
- if (!function_exists('wp_version_check') || !function_exists('get_core_checksums'))
 
216
  include_once(ABSPATH . '/wp-admin/includes/update.php');
217
-
218
  @wp_version_check();
219
-
220
  $current_update = false;
221
  ob_end_flush();
222
  ob_end_clean();
223
  $core = $this->mmb_get_transient('update_core');
224
-
225
  if (isset($core->updates) && !empty($core->updates)) {
226
  $updates = $core->updates[0];
227
  $updated = $core->updates[0];
@@ -229,10 +238,10 @@ class MMB_Installer extends MMB_Core
229
  return array(
230
  'upgraded' => ' updated'
231
  );
232
-
233
  if ($updated->response == "development" && $current->response == "upgrade") {
234
  return array(
235
- 'upgraded' => '<font color="#900">Unexpected error. Please upgrade manually.</font>'
236
  );
237
  } else if ($updated->response == $current->response || ($updated->response == "upgrade" && $current->response == "development")) {
238
  if ($updated->locale != $current->locale) {
@@ -259,11 +268,11 @@ class MMB_Installer extends MMB_Core
259
  );
260
  if ($current_update != false) {
261
  global $mmb_wp_version, $wp_filesystem, $wp_version;
262
-
263
  if (version_compare($wp_version, '3.1.9', '>')) {
264
  if (!class_exists('Core_Upgrader'))
265
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
266
-
267
  $core = new Core_Upgrader();
268
  $result = $core->upgrade($current_update);
269
  $this->mmb_maintenance_mode(false);
@@ -275,7 +284,7 @@ class MMB_Installer extends MMB_Core
275
  return array(
276
  'upgraded' => ' updated'
277
  );
278
-
279
  } else {
280
  if (!class_exists('WP_Upgrader')) {
281
  include_once(ABSPATH . 'wp-admin/includes/update.php');
@@ -291,19 +300,19 @@ class MMB_Installer extends MMB_Core
291
  );
292
  }
293
  }
294
-
295
  if (class_exists('WP_Upgrader')) {
296
  $upgrader_skin = new WP_Upgrader_Skin();
297
  $upgrader_skin->done_header = true;
298
-
299
  $upgrader = new WP_Upgrader($upgrader_skin);
300
-
301
  // Is an update available?
302
  if (!isset($current_update->response) || $current_update->response == 'latest')
303
  return array(
304
  'upgraded' => ' updated'
305
  );
306
-
307
  $res = $upgrader->fs_connect(array(
308
  ABSPATH,
309
  WP_CONTENT_DIR
@@ -312,42 +321,42 @@ class MMB_Installer extends MMB_Core
312
  return array(
313
  'error' => $this->mmb_get_error($res)
314
  );
315
-
316
  $wp_dir = trailingslashit($wp_filesystem->abspath());
317
-
318
  $core_package = false;
319
  if (isset($current_update->package) && !empty($current_update->package))
320
  $core_package = $current_update->package;
321
  elseif (isset($current_update->packages->full) && !empty($current_update->packages->full))
322
  $core_package = $current_update->packages->full;
323
-
324
  $download = $upgrader->download_package($core_package);
325
  if (is_wp_error($download))
326
  return array(
327
  'error' => $this->mmb_get_error($download)
328
  );
329
-
330
  $working_dir = $upgrader->unpack_package($download);
331
  if (is_wp_error($working_dir))
332
  return array(
333
  'error' => $this->mmb_get_error($working_dir)
334
  );
335
-
336
  if (!$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true)) {
337
  $wp_filesystem->delete($working_dir, true);
338
  return array(
339
  'error' => 'Unable to move update files.'
340
  );
341
  }
342
-
343
  $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
344
-
345
  require(ABSPATH . 'wp-admin/includes/update-core.php');
346
-
347
-
348
  $update_core = update_core($working_dir, $wp_dir);
349
  ob_end_clean();
350
-
351
  $this->mmb_maintenance_mode(false);
352
  if (is_wp_error($update_core))
353
  return array(
@@ -369,46 +378,46 @@ class MMB_Installer extends MMB_Core
369
  );
370
  }
371
  }
372
-
373
  function upgrade_plugins($plugins = false)
374
  {
375
  if (!$plugins || empty($plugins))
376
  return array(
377
  'error' => 'No plugin files for upgrade.'
378
  );
379
-
380
- $current = $this->mmb_get_transient('update_plugins');
381
- $versions = array();
382
- if(!empty($current)){
383
- foreach($plugins as $plugin => $data){
384
- if(isset($current->checked[$plugin])){
385
- $versions[$current->checked[$plugin]] = $plugin;
386
- }
387
  if ( !isset( $current->response[ $plugin ] ) ) {
388
  unset($plugins[$plugin]);
389
  }
390
- }
391
- }
392
  $return = array();
393
  if (class_exists('Plugin_Upgrader') && class_exists('Bulk_Plugin_Upgrader_Skin')) {
394
  $upgrader = new Plugin_Upgrader(new Bulk_Plugin_Upgrader_Skin(compact('nonce', 'url')));
395
  $result = $upgrader->bulk_upgrade(array_keys($plugins));
396
- if (!function_exists('wp_update_plugins'))
397
  include_once(ABSPATH . 'wp-includes/update.php');
398
-
399
  @wp_update_plugins();
400
- $current = $this->mmb_get_transient('update_plugins');
401
- if (!empty($result)) {
402
  foreach ($result as $plugin_slug => $plugin_info) {
403
  if (!$plugin_info || is_wp_error($plugin_info)) {
404
  $return[$plugin_slug] = $this->mmb_get_error($plugin_info);
405
  } else {
406
- if(!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)){
407
- $return[$plugin_slug] = 1;
408
- } else {
409
- update_option('mmb_forcerefresh', true);
410
- $return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
411
- }
412
  }
413
  }
414
  ob_end_clean();
@@ -426,44 +435,44 @@ class MMB_Installer extends MMB_Core
426
  );
427
  }
428
  }
429
-
430
  function upgrade_themes($themes = false)
431
  {
432
  if (!$themes || empty($themes))
433
  return array(
434
  'error' => 'No theme files for upgrade.'
435
  );
436
-
437
- $current = $this->mmb_get_transient('update_themes');
438
- $versions = array();
439
- if(!empty($current)){
440
- foreach($themes as $theme){
441
- if(isset($current->checked[$theme])){
442
- $versions[$current->checked[$theme]] = $theme;
443
- }
444
- }
445
- }
446
- if (class_exists('Theme_Upgrader') && class_exists('Bulk_Theme_Upgrader_Skin')) {
447
- $upgrader = new Theme_Upgrader(new Bulk_Theme_Upgrader_Skin(compact('title', 'nonce', 'url', 'theme')));
448
  $result = $upgrader->bulk_upgrade($themes);
449
-
450
- if (!function_exists('wp_update_themes'))
451
  include_once(ABSPATH . 'wp-includes/update.php');
452
-
453
  @wp_update_themes();
454
- $current = $this->mmb_get_transient('update_themes');
455
- $return = array();
456
  if (!empty($result)) {
457
  foreach ($result as $theme_tmp => $theme_info) {
458
- if (is_wp_error($theme_info) || empty($theme_info)) {
459
  $return[$theme_tmp] = $this->mmb_get_error($theme_info);
460
  } else {
461
- if(!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)){
462
- $return[$theme_tmp] = 1;
463
- } else {
464
- update_option('mmb_forcerefresh', true);
465
- $return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
466
- }
467
  }
468
  }
469
  return array(
@@ -480,14 +489,14 @@ class MMB_Installer extends MMB_Core
480
  );
481
  }
482
  }
483
-
484
  function upgrade_premium($premium = false)
485
  {
486
- global $mmb_plugin_url;
487
-
488
  if (!class_exists('WP_Upgrader'))
489
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
490
-
491
  if (!$premium || empty($premium))
492
  return array(
493
  'error' => 'No premium files for upgrade.'
@@ -499,50 +508,50 @@ class MMB_Installer extends MMB_Core
499
  $plugins = array();
500
  $result = array();
501
  $premium_update = array();
502
- $premium_update = apply_filters('mwp_premium_perform_update', $premium_update);
503
- if (!empty($premium_update)) {
504
-
505
- foreach ($premium as $pr) {
506
- foreach ($premium_update as $key => $update) {
507
- $update = array_change_key_case($update, CASE_LOWER);
508
- if ($update['name'] == $pr['name']) {
509
-
510
- // prepare bulk updates for premiums that use WordPress upgrader
511
- if(isset($update['type'])){
512
- if($update['type'] == 'plugin'){
513
- if(isset($update['slug']) && !empty($update['slug']))
514
- $plugins[$update['slug']] = $update;
515
- }
516
-
517
- if($update['type'] == 'theme'){
518
- if(isset($update['template']) && !empty($update['template']))
519
- $themes[$update['template']] = $update;
520
- }
521
- }
522
- } else {
523
- unset($premium_update[$key]);
524
- }
525
- }
526
- }
527
-
528
- // try default wordpress upgrader
529
- if(!empty($plugins)){
530
- $updateplugins = $this->upgrade_plugins(array_values($plugins));
531
- if(!empty($updateplugins) && isset($updateplugins['upgraded'])){
532
- foreach ($premium_update as $key => $update) {
533
- $update = array_change_key_case($update, CASE_LOWER);
534
- foreach($updateplugins['upgraded'] as $slug => $upgrade){
535
- if( isset($update['slug']) && $update['slug'] == $slug){
536
- if( $upgrade == 1 )
537
- unset($premium_update[$key]);
538
-
539
- $pr_update['plugins']['upgraded'][md5($update['name'])] = $upgrade;
540
- }
541
- }
542
- }
543
- }
544
- }
545
-
546
  // if(!empty($themes)){
547
  // $updatethemes = $this->upgrade_themes(array_keys($themes));
548
  // if(!empty($updatethemes) && isset($updatethemes['upgraded'])){
@@ -559,46 +568,46 @@ class MMB_Installer extends MMB_Core
559
  // }
560
  // }
561
  // }
562
-
563
- //try direct install with overwrite
564
- if(!empty($premium_update)){
565
- foreach ($premium_update as $update) {
566
- $update = array_change_key_case($update, CASE_LOWER);
567
- $update_result = false;
568
- if (isset($update['url'])) {
569
- if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
570
- $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
571
-
572
- $upgrader_skin = new WP_Upgrader_Skin();
573
- $upgrader_skin->done_header = true;
574
- $upgrader = new WP_Upgrader();
575
- @$update_result = $upgrader->run(array(
576
- 'package' => $update['url'],
577
- 'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
578
- 'clear_destination' => true,
579
- 'clear_working' => true,
580
- 'is_multi' => true,
581
- 'hook_extra' => array()
582
- ));
583
- $update_result = !$update_result || is_wp_error($update_result) ? $this->mmb_get_error($update_result) : 1;
584
-
585
- } else if (isset($update['callback'])) {
586
- if (is_array($update['callback'])) {
587
- $update_result = call_user_func(array( $update['callback'][0], $update['callback'][1] ));
588
- } else if (is_string($update['callback'])) {
589
- $update_result = call_user_func($update['callback']);
590
- } else {
591
- $update_result = 'Upgrade function "' . $update['callback'] . '" does not exists.';
592
- }
593
-
594
- $update_result = $update_result !== true ? $this->mmb_get_error($update_result) : 1;
595
- } else
596
- $update_result = 'Bad update params.';
597
-
598
- $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
599
- }
600
- }
601
- return $pr_update;
602
  } else {
603
  foreach ($premium as $pr) {
604
  $result[$pr['type'] . 's']['upgraded'][md5($pr['name'])] = 'This premium update is not registered.';
@@ -606,11 +615,11 @@ class MMB_Installer extends MMB_Core
606
  return $result;
607
  }
608
  }
609
-
610
  function get_upgradable_plugins( $filter = array() )
611
  {
612
  $current = $this->mmb_get_transient('update_plugins');
613
-
614
  $upgradable_plugins = array();
615
  if (!empty($current->response)) {
616
  if (!function_exists('get_plugin_data'))
@@ -618,11 +627,11 @@ class MMB_Installer extends MMB_Core
618
  foreach ($current->response as $plugin_path => $plugin_data) {
619
  if ($plugin_path == 'worker/init.php')
620
  continue;
621
-
622
- $data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_path);
623
- if(isset($data['Name']) && in_array($data['Name'], $filter))
624
- continue;
625
-
626
  if (strlen($data['Name']) > 0 && strlen($data['Version']) > 0) {
627
  $current->response[$plugin_path]->name = $data['Name'];
628
  $current->response[$plugin_path]->old_version = $data['Version'];
@@ -635,73 +644,73 @@ class MMB_Installer extends MMB_Core
635
  } else
636
  return array();
637
  }
638
-
639
  function get_upgradable_themes( $filter = array() )
640
  {
641
  if(function_exists('wp_get_themes')){
642
- $all_themes = wp_get_themes();
643
- $upgrade_themes = array();
644
-
645
- $current = $this->mmb_get_transient('update_themes');
646
- if (!empty($current->response)) {
647
- foreach ((array) $all_themes as $theme_template => $theme_data) {
648
- if(isset($theme_data->{'Parent Theme'}) && !empty($theme_data->{'Parent Theme'}))
649
- continue;
650
-
651
- if(isset($theme_data->Name) && in_array($theme_data->Name, $filter))
652
- continue;
653
-
654
- foreach ($current->response as $current_themes => $theme) {
655
- if ($theme_data->Template == $current_themes) {
656
- if (strlen($theme_data->Name) > 0 && strlen($theme_data->Version) > 0) {
657
- $current->response[$current_themes]['name'] = $theme_data->Name;
658
- $current->response[$current_themes]['old_version'] = $theme_data->Version;
659
- $current->response[$current_themes]['theme_tmp'] = $theme_data->Template;
660
- $upgrade_themes[] = $current->response[$current_themes];
661
- }
662
- }
663
- }
664
- }
665
- }
666
  }else{
667
- $all_themes = get_themes();
668
-
669
- $upgrade_themes = array();
670
-
671
- $current = $this->mmb_get_transient('update_themes');
672
- if (!empty($current->response)) {
673
- foreach ((array) $all_themes as $theme_template => $theme_data) {
674
- if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
675
- continue;
676
-
677
- if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
678
- continue;
679
-
680
- foreach ($current->response as $current_themes => $theme) {
681
- if ($theme_data['Template'] == $current_themes) {
682
- if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
683
- $current->response[$current_themes]['name'] = $theme_data['Name'];
684
- $current->response[$current_themes]['old_version'] = $theme_data['Version'];
685
- $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
686
- $upgrade_themes[] = $current->response[$current_themes];
687
- }
688
- }
689
- }
690
- }
691
- }
692
  }
693
-
694
-
695
  return $upgrade_themes;
696
  }
697
-
698
  function get($args)
699
  {
700
  if (empty($args))
701
  return false;
702
-
703
  //Args: $items('plugins,'themes'), $type (active || inactive), $search(name string)
704
-
705
  $return = array();
706
  if (is_array($args['items']) && in_array('plugins', $args['items'])) {
707
  $return['plugins'] = $this->get_plugins($args);
@@ -709,17 +718,17 @@ class MMB_Installer extends MMB_Core
709
  if (is_array($args['items']) && in_array('themes', $args['items'])) {
710
  $return['themes'] = $this->get_themes($args);
711
  }
712
-
713
  return $return;
714
  }
715
-
716
  function get_plugins($args)
717
  {
718
  if (empty($args))
719
  return false;
720
-
721
  extract($args);
722
-
723
  if (!function_exists('get_plugins')) {
724
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
725
  }
@@ -732,7 +741,7 @@ class MMB_Installer extends MMB_Core
732
  $activated_plugins = get_option('active_plugins');
733
  if (!$activated_plugins)
734
  $activated_plugins = array();
735
-
736
  $br_a = 0;
737
  $br_i = 0;
738
  foreach ($all_plugins as $path => $plugin) {
@@ -740,26 +749,26 @@ class MMB_Installer extends MMB_Core
740
  if (in_array($path, $activated_plugins)) {
741
  $plugins['active'][$br_a]['path'] = $path;
742
  $plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
743
- $plugins['active'][$br_a]['version'] = $plugin['Version'];
744
  $br_a++;
745
  }
746
-
747
  if (!in_array($path, $activated_plugins)) {
748
  $plugins['inactive'][$br_i]['path'] = $path;
749
  $plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
750
- $plugins['inactive'][$br_i]['version'] = $plugin['Version'];
751
  $br_i++;
752
  }
753
-
754
  }
755
-
756
  if ($search) {
757
  foreach ($plugins['active'] as $k => $plugin) {
758
  if (!stristr($plugin['name'], $search)) {
759
  unset($plugins['active'][$k]);
760
  }
761
  }
762
-
763
  foreach ($plugins['inactive'] as $k => $plugin) {
764
  if (!stristr($plugin['name'], $search)) {
765
  unset($plugins['inactive'][$k]);
@@ -768,116 +777,116 @@ class MMB_Installer extends MMB_Core
768
  }
769
  }
770
  }
771
-
772
  return $plugins;
773
  }
774
-
775
  function get_themes($args)
776
  {
777
  if (empty($args))
778
  return false;
779
-
780
  extract($args);
781
-
782
  if (!function_exists('wp_get_themes')) {
783
  include_once(ABSPATH . WPINC . '/theme.php');
784
  }
785
  if(function_exists('wp_get_themes')){
786
- $all_themes = wp_get_themes();
787
- $themes = array(
788
- 'active' => array(),
789
- 'inactive' => array()
790
- );
791
-
792
- if (is_array($all_themes) && !empty($all_themes)) {
793
- $current_theme = get_current_theme();
794
-
795
- $br_a = 0;
796
- $br_i = 0;
797
- foreach ($all_themes as $theme_name => $theme) {
798
- if ($current_theme == strip_tags($theme->Name)) {
799
- $themes['active'][$br_a]['path'] = $theme->Template;
800
- $themes['active'][$br_a]['name'] = strip_tags($theme->Name);
801
- $themes['active'][$br_a]['version'] = $theme->Version;
802
- $themes['active'][$br_a]['stylesheet'] = $theme->Stylesheet;
803
- $br_a++;
804
- }
805
-
806
- if ($current_theme != strip_tags($theme->Name)) {
807
- $themes['inactive'][$br_i]['path'] = $theme->Template;
808
- $themes['inactive'][$br_i]['name'] = strip_tags($theme->Name);
809
- $themes['inactive'][$br_i]['version'] = $theme->Version;
810
- $themes['inactive'][$br_i]['stylesheet'] = $theme->Stylesheet;
811
- $br_i++;
812
- }
813
-
814
- }
815
-
816
- if ($search) {
817
- foreach ($themes['active'] as $k => $theme) {
818
- if (!stristr($theme['name'], $search)) {
819
- unset($themes['active'][$k]);
820
- }
821
- }
822
-
823
- foreach ($themes['inactive'] as $k => $theme) {
824
- if (!stristr($theme['name'], $search)) {
825
- unset($themes['inactive'][$k]);
826
- }
827
- }
828
- }
829
- }
830
- }else{
831
- $all_themes = get_themes();
832
- $themes = array(
833
- 'active' => array(),
834
- 'inactive' => array()
835
- );
836
-
837
- if (is_array($all_themes) && !empty($all_themes)) {
838
- $current_theme = get_current_theme();
839
-
840
- $br_a = 0;
841
- $br_i = 0;
842
- foreach ($all_themes as $theme_name => $theme) {
843
- if ($current_theme == $theme_name) {
844
- $themes['active'][$br_a]['path'] = $theme['Template'];
845
- $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
846
- $themes['active'][$br_a]['version'] = $theme['Version'];
847
- $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
848
- $br_a++;
849
- }
850
-
851
- if ($current_theme != $theme_name) {
852
- $themes['inactive'][$br_i]['path'] = $theme['Template'];
853
- $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
854
- $themes['inactive'][$br_i]['version'] = $theme['Version'];
855
- $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
856
- $br_i++;
857
- }
858
-
859
- }
860
-
861
- if ($search) {
862
- foreach ($themes['active'] as $k => $theme) {
863
- if (!stristr($theme['name'], $search)) {
864
- unset($themes['active'][$k]);
865
- }
866
- }
867
-
868
- foreach ($themes['inactive'] as $k => $theme) {
869
- if (!stristr($theme['name'], $search)) {
870
- unset($themes['inactive'][$k]);
871
- }
872
- }
873
- }
874
- }
875
-
876
- }
877
-
878
  return $themes;
879
  }
880
-
881
  function edit($args)
882
  {
883
  extract($args);
@@ -889,7 +898,7 @@ class MMB_Installer extends MMB_Core
889
  }
890
  return $return;
891
  }
892
-
893
  function edit_plugins($args)
894
  {
895
  extract($args);
@@ -912,7 +921,7 @@ class MMB_Installer extends MMB_Core
912
  default:
913
  break;
914
  }
915
-
916
  if (is_wp_error($result)) {
917
  $result = array(
918
  'error' => $result->get_error_message()
@@ -926,10 +935,10 @@ class MMB_Installer extends MMB_Core
926
  }
927
  $return[$item['name']] = $result;
928
  }
929
-
930
  return $return;
931
  }
932
-
933
  function edit_themes($args)
934
  {
935
  extract($args);
@@ -945,7 +954,7 @@ class MMB_Installer extends MMB_Core
945
  default:
946
  break;
947
  }
948
-
949
  if (is_wp_error($result)) {
950
  $result = array(
951
  'error' => $result->get_error_message()
@@ -959,9 +968,9 @@ class MMB_Installer extends MMB_Core
959
  }
960
  $return[$item['name']] = $result;
961
  }
962
-
963
  return $return;
964
-
965
  }
966
  }
967
  ?>
1
  <?php
2
  /*************************************************************
3
+ *
4
  * installer.class.php
5
+ *
6
  * Upgrade WordPress
7
+ *
8
+ *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
24
  @include_once(ABSPATH . 'wp-admin/includes/misc.php');
25
  @include_once(ABSPATH . 'wp-admin/includes/template.php');
26
  @include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
27
+
28
  global $wp_filesystem;
29
  if (!$wp_filesystem)
30
  WP_Filesystem();
31
  }
32
+
33
  function mmb_maintenance_mode($enable = false, $maintenance_message = '')
34
  {
35
  global $wp_filesystem;
36
+
37
  $maintenance_message .= '<?php $upgrading = ' . time() . '; ?>';
38
+
39
  $file = $wp_filesystem->abspath() . '.maintenance';
40
  if ($enable) {
41
  $wp_filesystem->delete($file);
44
  $wp_filesystem->delete($file);
45
  }
46
  }
47
+
48
  function install_remote_file($params)
49
  {
50
  global $wp_filesystem;
51
  extract($params);
52
+
53
  if (!isset($package) || empty($package))
54
  return array(
55
  'error' => '<p>No files received. Internal error.</p>'
56
  );
57
+
58
+ if (!$this->is_server_writable()) {
59
+ return array(
60
+ 'error' => 'Failed, please <a target="_blank" href="http://managewp.com/user-guide/faq/my-pluginsthemes-fail-to-update-or-i-receive-a-yellow-ftp-warning">add FTP details</a>'
61
+ );
62
+ }
63
+
64
  if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
65
  return array(
66
  'error' => '<p>Site under maintanace.</p>'
67
  );
68
+
69
  if (!class_exists('WP_Upgrader'))
70
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
71
+
72
  $upgrader_skin = new WP_Upgrader_Skin();
73
  $upgrader_skin->done_header = true;
74
+
75
  $upgrader = new WP_Upgrader($upgrader_skin);
76
  $destination = $type == 'themes' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR;
77
  $clear_destination = isset($clear_destination) ? $clear_destination : false;
78
+
79
  foreach ($package as $package_url) {
80
  $key = basename($package_url);
81
  $install_info[$key] = @$upgrader->run(array(
86
  'hook_extra' => array()
87
  ));
88
  }
89
+
90
  if ($activate) {
91
  if ($type == 'plugins') {
92
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
104
  } else if (count($install_info) == 1) {
105
  global $wp_themes;
106
  include_once(ABSPATH . 'wp-includes/theme.php');
107
+
108
  $wp_themes = null;
109
  unset($wp_themes); //prevent theme data caching
110
  if(function_exists('wp_get_themes')){
111
+ $all_themes = wp_get_themes();
112
+ foreach ($all_themes as $theme_name => $theme_data) {
113
+ foreach ($install_info as $key => $install) {
114
+ if (!$install || is_wp_error($install))
115
+ continue;
116
+
117
+ if ($theme_data->Template == $install['destination_name']) {
118
+ $install_info[$key]['activated'] = switch_theme($theme_data->Template, $theme_data->Stylesheet);
119
+ }
120
+ }
121
+ }
122
  }else{
123
+ $all_themes = get_themes();
124
+ foreach ($all_themes as $theme_name => $theme_data) {
125
+ foreach ($install_info as $key => $install) {
126
+ if (!$install || is_wp_error($install))
127
+ continue;
128
+
129
+ if ($theme_data['Template'] == $install['destination_name']) {
130
+ $install_info[$key]['activated'] = switch_theme($theme_data['Template'], $theme_data['Stylesheet']);
131
+ }
132
+ }
133
+ }
134
+ }
135
  }
136
  }
137
  ob_clean();
138
  $this->mmb_maintenance_mode(false);
139
  return $install_info;
140
  }
141
+
142
  function do_upgrade($params = null)
143
  {
144
+
145
+
146
+ if ($params == null || empty($params))
147
  return array(
148
+ 'error' => 'No upgrades passed.'
149
  );
150
+
151
  if (!$this->is_server_writable()) {
152
  return array(
153
  'error' => 'Failed, please <a target="_blank" href="http://managewp.com/user-guide/faq/my-pluginsthemes-fail-to-update-or-i-receive-a-yellow-ftp-warning">add FTP details</a>'
154
  );
155
  }
156
+
157
+
158
  $params = isset($params['upgrades_all']) ? $params['upgrades_all'] : $params;
159
+
160
  $core_upgrade = isset($params['wp_upgrade']) ? $params['wp_upgrade'] : array();
161
  $upgrade_plugins = isset($params['upgrade_plugins']) ? $params['upgrade_plugins'] : array();
162
  $upgrade_themes = isset($params['upgrade_themes']) ? $params['upgrade_themes'] : array();
163
+
164
  $upgrades = array();
165
  $premium_upgrades = array();
166
  if (!empty($core_upgrade)) {
167
  $upgrades['core'] = $this->upgrade_core($core_upgrade);
168
  }
169
+
170
  if (!empty($upgrade_plugins)) {
171
  $plugin_files = array();
172
  foreach ($upgrade_plugins as $plugin) {
177
  }
178
  if (!empty($plugin_files))
179
  $upgrades['plugins'] = $this->upgrade_plugins($plugin_files);
180
+
181
  }
182
+
183
  if (!empty($upgrade_themes)) {
184
  $theme_temps = array();
185
  foreach ($upgrade_themes as $theme) {
188
  else
189
  $premium_upgrades[md5($theme['name'])] = $theme;
190
  }
191
+
192
  if (!empty($theme_temps))
193
  $upgrades['themes'] = $this->upgrade_themes($theme_temps);
194
+
195
  }
196
+
197
  if (!empty($premium_upgrades)) {
198
  $premium_upgrades = $this->upgrade_premium($premium_upgrades);
199
  if (!empty($premium_upgrades)) {
212
  $this->mmb_maintenance_mode(false);
213
  return $upgrades;
214
  }
215
+
216
  /**
217
  * Upgrades WordPress locally
218
  *
220
  function upgrade_core($current)
221
  {
222
  ob_start();
223
+
224
+ if (file_exists(ABSPATH . '/wp-admin/includes/update.php'))
225
  include_once(ABSPATH . '/wp-admin/includes/update.php');
226
+
227
  @wp_version_check();
228
+
229
  $current_update = false;
230
  ob_end_flush();
231
  ob_end_clean();
232
  $core = $this->mmb_get_transient('update_core');
233
+
234
  if (isset($core->updates) && !empty($core->updates)) {
235
  $updates = $core->updates[0];
236
  $updated = $core->updates[0];
238
  return array(
239
  'upgraded' => ' updated'
240
  );
241
+
242
  if ($updated->response == "development" && $current->response == "upgrade") {
243
  return array(
244
+ 'error' => '<font color="#900">Unexpected error. Please upgrade manually.</font>'
245
  );
246
  } else if ($updated->response == $current->response || ($updated->response == "upgrade" && $current->response == "development")) {
247
  if ($updated->locale != $current->locale) {
268
  );
269
  if ($current_update != false) {
270
  global $mmb_wp_version, $wp_filesystem, $wp_version;
271
+
272
  if (version_compare($wp_version, '3.1.9', '>')) {
273
  if (!class_exists('Core_Upgrader'))
274
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
275
+
276
  $core = new Core_Upgrader();
277
  $result = $core->upgrade($current_update);
278
  $this->mmb_maintenance_mode(false);
284
  return array(
285
  'upgraded' => ' updated'
286
  );
287
+
288
  } else {
289
  if (!class_exists('WP_Upgrader')) {
290
  include_once(ABSPATH . 'wp-admin/includes/update.php');
300
  );
301
  }
302
  }
303
+
304
  if (class_exists('WP_Upgrader')) {
305
  $upgrader_skin = new WP_Upgrader_Skin();
306
  $upgrader_skin->done_header = true;
307
+
308
  $upgrader = new WP_Upgrader($upgrader_skin);
309
+
310
  // Is an update available?
311
  if (!isset($current_update->response) || $current_update->response == 'latest')
312
  return array(
313
  'upgraded' => ' updated'
314
  );
315
+
316
  $res = $upgrader->fs_connect(array(
317
  ABSPATH,
318
  WP_CONTENT_DIR
321
  return array(
322
  'error' => $this->mmb_get_error($res)
323
  );
324
+
325
  $wp_dir = trailingslashit($wp_filesystem->abspath());
326
+
327
  $core_package = false;
328
  if (isset($current_update->package) && !empty($current_update->package))
329
  $core_package = $current_update->package;
330
  elseif (isset($current_update->packages->full) && !empty($current_update->packages->full))
331
  $core_package = $current_update->packages->full;
332
+
333
  $download = $upgrader->download_package($core_package);
334
  if (is_wp_error($download))
335
  return array(
336
  'error' => $this->mmb_get_error($download)
337
  );
338
+
339
  $working_dir = $upgrader->unpack_package($download);
340
  if (is_wp_error($working_dir))
341
  return array(
342
  'error' => $this->mmb_get_error($working_dir)
343
  );
344
+
345
  if (!$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true)) {
346
  $wp_filesystem->delete($working_dir, true);
347
  return array(
348
  'error' => 'Unable to move update files.'
349
  );
350
  }
351
+
352
  $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
353
+
354
  require(ABSPATH . 'wp-admin/includes/update-core.php');
355
+
356
+
357
  $update_core = update_core($working_dir, $wp_dir);
358
  ob_end_clean();
359
+
360
  $this->mmb_maintenance_mode(false);
361
  if (is_wp_error($update_core))
362
  return array(
378
  );
379
  }
380
  }
381
+
382
  function upgrade_plugins($plugins = false)
383
  {
384
  if (!$plugins || empty($plugins))
385
  return array(
386
  'error' => 'No plugin files for upgrade.'
387
  );
388
+
389
+ $current = $this->mmb_get_transient('update_plugins');
390
+ $versions = array();
391
+ if(!empty($current)){
392
+ foreach($plugins as $plugin => $data){
393
+ if(isset($current->checked[$plugin])){
394
+ $versions[$current->checked[$plugin]] = $plugin;
395
+ }
396
  if ( !isset( $current->response[ $plugin ] ) ) {
397
  unset($plugins[$plugin]);
398
  }
399
+ }
400
+ }
401
  $return = array();
402
  if (class_exists('Plugin_Upgrader') && class_exists('Bulk_Plugin_Upgrader_Skin')) {
403
  $upgrader = new Plugin_Upgrader(new Bulk_Plugin_Upgrader_Skin(compact('nonce', 'url')));
404
  $result = $upgrader->bulk_upgrade(array_keys($plugins));
405
+ if (!function_exists('wp_update_plugins'))
406
  include_once(ABSPATH . 'wp-includes/update.php');
407
+
408
  @wp_update_plugins();
409
+ $current = $this->mmb_get_transient('update_plugins');
410
+ if (!empty($result)) {
411
  foreach ($result as $plugin_slug => $plugin_info) {
412
  if (!$plugin_info || is_wp_error($plugin_info)) {
413
  $return[$plugin_slug] = $this->mmb_get_error($plugin_info);
414
  } else {
415
+ if(!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)){
416
+ $return[$plugin_slug] = 1;
417
+ } else {
418
+ update_option('mmb_forcerefresh', true);
419
+ $return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
420
+ }
421
  }
422
  }
423
  ob_end_clean();
435
  );
436
  }
437
  }
438
+
439
  function upgrade_themes($themes = false)
440
  {
441
  if (!$themes || empty($themes))
442
  return array(
443
  'error' => 'No theme files for upgrade.'
444
  );
445
+
446
+ $current = $this->mmb_get_transient('update_themes');
447
+ $versions = array();
448
+ if(!empty($current)){
449
+ foreach($themes as $theme){
450
+ if(isset($current->checked[$theme])){
451
+ $versions[$current->checked[$theme]] = $theme;
452
+ }
453
+ }
454
+ }
455
+ if (class_exists('Theme_Upgrader') && class_exists('Bulk_Theme_Upgrader_Skin')) {
456
+ $upgrader = new Theme_Upgrader(new Bulk_Theme_Upgrader_Skin(compact('title', 'nonce', 'url', 'theme')));
457
  $result = $upgrader->bulk_upgrade($themes);
458
+
459
+ if (!function_exists('wp_update_themes'))
460
  include_once(ABSPATH . 'wp-includes/update.php');
461
+
462
  @wp_update_themes();
463
+ $current = $this->mmb_get_transient('update_themes');
464
+ $return = array();
465
  if (!empty($result)) {
466
  foreach ($result as $theme_tmp => $theme_info) {
467
+ if (is_wp_error($theme_info) || empty($theme_info)) {
468
  $return[$theme_tmp] = $this->mmb_get_error($theme_info);
469
  } else {
470
+ if(!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)){
471
+ $return[$theme_tmp] = 1;
472
+ } else {
473
+ update_option('mmb_forcerefresh', true);
474
+ $return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
475
+ }
476
  }
477
  }
478
  return array(
489
  );
490
  }
491
  }
492
+
493
  function upgrade_premium($premium = false)
494
  {
495
+ global $mmb_plugin_url;
496
+
497
  if (!class_exists('WP_Upgrader'))
498
  include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
499
+
500
  if (!$premium || empty($premium))
501
  return array(
502
  'error' => 'No premium files for upgrade.'
508
  $plugins = array();
509
  $result = array();
510
  $premium_update = array();
511
+ $premium_update = apply_filters('mwp_premium_perform_update', $premium_update);
512
+ if (!empty($premium_update)) {
513
+
514
+ foreach ($premium as $pr) {
515
+ foreach ($premium_update as $key => $update) {
516
+ $update = array_change_key_case($update, CASE_LOWER);
517
+ if ($update['name'] == $pr['name']) {
518
+
519
+ // prepare bulk updates for premiums that use WordPress upgrader
520
+ if(isset($update['type'])){
521
+ if($update['type'] == 'plugin'){
522
+ if(isset($update['slug']) && !empty($update['slug']))
523
+ $plugins[$update['slug']] = $update;
524
+ }
525
+
526
+ if($update['type'] == 'theme'){
527
+ if(isset($update['template']) && !empty($update['template']))
528
+ $themes[$update['template']] = $update;
529
+ }
530
+ }
531
+ } else {
532
+ unset($premium_update[$key]);
533
+ }
534
+ }
535
+ }
536
+
537
+ // try default wordpress upgrader
538
+ if(!empty($plugins)){
539
+ $updateplugins = $this->upgrade_plugins(array_values($plugins));
540
+ if(!empty($updateplugins) && isset($updateplugins['upgraded'])){
541
+ foreach ($premium_update as $key => $update) {
542
+ $update = array_change_key_case($update, CASE_LOWER);
543
+ foreach($updateplugins['upgraded'] as $slug => $upgrade){
544
+ if( isset($update['slug']) && $update['slug'] == $slug){
545
+ if( $upgrade == 1 )
546
+ unset($premium_update[$key]);
547
+
548
+ $pr_update['plugins']['upgraded'][md5($update['name'])] = $upgrade;
549
+ }
550
+ }
551
+ }
552
+ }
553
+ }
554
+
555
  // if(!empty($themes)){
556
  // $updatethemes = $this->upgrade_themes(array_keys($themes));
557
  // if(!empty($updatethemes) && isset($updatethemes['upgraded'])){
568
  // }
569
  // }
570
  // }
571
+
572
+ //try direct install with overwrite
573
+ if(!empty($premium_update)){
574
+ foreach ($premium_update as $update) {
575
+ $update = array_change_key_case($update, CASE_LOWER);
576
+ $update_result = false;
577
+ if (isset($update['url'])) {
578
+ if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
579
+ $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
580
+
581
+ $upgrader_skin = new WP_Upgrader_Skin();
582
+ $upgrader_skin->done_header = true;
583
+ $upgrader = new WP_Upgrader();
584
+ @$update_result = $upgrader->run(array(
585
+ 'package' => $update['url'],
586
+ 'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
587
+ 'clear_destination' => true,
588
+ 'clear_working' => true,
589
+ 'is_multi' => true,
590
+ 'hook_extra' => array()
591
+ ));
592
+ $update_result = !$update_result || is_wp_error($update_result) ? $this->mmb_get_error($update_result) : 1;
593
+
594
+ } else if (isset($update['callback'])) {
595
+ if (is_array($update['callback'])) {
596
+ $update_result = call_user_func(array( $update['callback'][0], $update['callback'][1] ));
597
+ } else if (is_string($update['callback'])) {
598
+ $update_result = call_user_func($update['callback']);
599
+ } else {
600
+ $update_result = 'Upgrade function "' . $update['callback'] . '" does not exists.';
601
+ }
602
+
603
+ $update_result = $update_result !== true ? $this->mmb_get_error($update_result) : 1;
604
+ } else
605
+ $update_result = 'Bad update params.';
606
+
607
+ $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
608
+ }
609
+ }
610
+ return $pr_update;
611
  } else {
612
  foreach ($premium as $pr) {
613
  $result[$pr['type'] . 's']['upgraded'][md5($pr['name'])] = 'This premium update is not registered.';
615
  return $result;
616
  }
617
  }
618
+
619
  function get_upgradable_plugins( $filter = array() )
620
  {
621
  $current = $this->mmb_get_transient('update_plugins');
622
+
623
  $upgradable_plugins = array();
624
  if (!empty($current->response)) {
625
  if (!function_exists('get_plugin_data'))
627
  foreach ($current->response as $plugin_path => $plugin_data) {
628
  if ($plugin_path == 'worker/init.php')
629
  continue;
630
+
631
+ $data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_path);
632
+ if(isset($data['Name']) && in_array($data['Name'], $filter))
633
+ continue;
634
+
635
  if (strlen($data['Name']) > 0 && strlen($data['Version']) > 0) {
636
  $current->response[$plugin_path]->name = $data['Name'];
637
  $current->response[$plugin_path]->old_version = $data['Version'];
644
  } else
645
  return array();
646
  }
647
+
648
  function get_upgradable_themes( $filter = array() )
649
  {
650
  if(function_exists('wp_get_themes')){
651
+ $all_themes = wp_get_themes();
652
+ $upgrade_themes = array();
653
+
654
+ $current = $this->mmb_get_transient('update_themes');
655
+ if (!empty($current->response)) {
656
+ foreach ((array) $all_themes as $theme_template => $theme_data) {
657
+ if(isset($theme_data->{'Parent Theme'}) && !empty($theme_data->{'Parent Theme'}))
658
+ continue;
659
+
660
+ if(isset($theme_data->Name) && in_array($theme_data->Name, $filter))
661
+ continue;
662
+
663
+ foreach ($current->response as $current_themes => $theme) {
664
+ if ($theme_data->Template == $current_themes) {
665
+ if (strlen($theme_data->Name) > 0 && strlen($theme_data->Version) > 0) {
666
+ $current->response[$current_themes]['name'] = $theme_data->Name;
667
+ $current->response[$current_themes]['old_version'] = $theme_data->Version;
668
+ $current->response[$current_themes]['theme_tmp'] = $theme_data->Template;
669
+ $upgrade_themes[] = $current->response[$current_themes];
670
+ }
671
+ }
672
+ }
673
+ }
674
+ }
675
  }else{
676
+ $all_themes = get_themes();
677
+
678
+ $upgrade_themes = array();
679
+
680
+ $current = $this->mmb_get_transient('update_themes');
681
+ if (!empty($current->response)) {
682
+ foreach ((array) $all_themes as $theme_template => $theme_data) {
683
+ if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
684
+ continue;
685
+
686
+ if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
687
+ continue;
688
+
689
+ foreach ($current->response as $current_themes => $theme) {
690
+ if ($theme_data['Template'] == $current_themes) {
691
+ if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
692
+ $current->response[$current_themes]['name'] = $theme_data['Name'];
693
+ $current->response[$current_themes]['old_version'] = $theme_data['Version'];
694
+ $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
695
+ $upgrade_themes[] = $current->response[$current_themes];
696
+ }
697
+ }
698
+ }
699
+ }
700
+ }
701
  }
702
+
703
+
704
  return $upgrade_themes;
705
  }
706
+
707
  function get($args)
708
  {
709
  if (empty($args))
710
  return false;
711
+
712
  //Args: $items('plugins,'themes'), $type (active || inactive), $search(name string)
713
+
714
  $return = array();
715
  if (is_array($args['items']) && in_array('plugins', $args['items'])) {
716
  $return['plugins'] = $this->get_plugins($args);
718
  if (is_array($args['items']) && in_array('themes', $args['items'])) {
719
  $return['themes'] = $this->get_themes($args);
720
  }
721
+
722
  return $return;
723
  }
724
+
725
  function get_plugins($args)
726
  {
727
  if (empty($args))
728
  return false;
729
+
730
  extract($args);
731
+
732
  if (!function_exists('get_plugins')) {
733
  include_once(ABSPATH . 'wp-admin/includes/plugin.php');
734
  }
741
  $activated_plugins = get_option('active_plugins');
742
  if (!$activated_plugins)
743
  $activated_plugins = array();
744
+
745
  $br_a = 0;
746
  $br_i = 0;
747
  foreach ($all_plugins as $path => $plugin) {
749
  if (in_array($path, $activated_plugins)) {
750
  $plugins['active'][$br_a]['path'] = $path;
751
  $plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
752
+ $plugins['active'][$br_a]['version'] = $plugin['Version'];
753
  $br_a++;
754
  }
755
+
756
  if (!in_array($path, $activated_plugins)) {
757
  $plugins['inactive'][$br_i]['path'] = $path;
758
  $plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
759
+ $plugins['inactive'][$br_i]['version'] = $plugin['Version'];
760
  $br_i++;
761
  }
762
+
763
  }
764
+
765
  if ($search) {
766
  foreach ($plugins['active'] as $k => $plugin) {
767
  if (!stristr($plugin['name'], $search)) {
768
  unset($plugins['active'][$k]);
769
  }
770
  }
771
+
772
  foreach ($plugins['inactive'] as $k => $plugin) {
773
  if (!stristr($plugin['name'], $search)) {
774
  unset($plugins['inactive'][$k]);
777
  }
778
  }
779
  }
780
+
781
  return $plugins;
782
  }
783
+
784
  function get_themes($args)
785
  {
786
  if (empty($args))
787
  return false;
788
+
789
  extract($args);
790
+
791
  if (!function_exists('wp_get_themes')) {
792
  include_once(ABSPATH . WPINC . '/theme.php');
793
  }
794
  if(function_exists('wp_get_themes')){
795
+ $all_themes = wp_get_themes();
796
+ $themes = array(
797
+ 'active' => array(),
798
+ 'inactive' => array()
799
+ );
800
+
801
+ if (is_array($all_themes) && !empty($all_themes)) {
802
+ $current_theme = get_current_theme();
803
+
804
+ $br_a = 0;
805
+ $br_i = 0;
806
+ foreach ($all_themes as $theme_name => $theme) {
807
+ if ($current_theme == strip_tags($theme->Name)) {
808
+ $themes['active'][$br_a]['path'] = $theme->Template;
809
+ $themes['active'][$br_a]['name'] = strip_tags($theme->Name);
810
+ $themes['active'][$br_a]['version'] = $theme->Version;
811
+ $themes['active'][$br_a]['stylesheet'] = $theme->Stylesheet;
812
+ $br_a++;
813
+ }
814
+
815
+ if ($current_theme != strip_tags($theme->Name)) {
816
+ $themes['inactive'][$br_i]['path'] = $theme->Template;
817
+ $themes['inactive'][$br_i]['name'] = strip_tags($theme->Name);
818
+ $themes['inactive'][$br_i]['version'] = $theme->Version;
819
+ $themes['inactive'][$br_i]['stylesheet'] = $theme->Stylesheet;
820
+ $br_i++;
821
+ }
822
+
823
+ }
824
+
825
+ if ($search) {
826
+ foreach ($themes['active'] as $k => $theme) {
827
+ if (!stristr($theme['name'], $search)) {
828
+ unset($themes['active'][$k]);
829
+ }
830
+ }
831
+
832
+ foreach ($themes['inactive'] as $k => $theme) {
833
+ if (!stristr($theme['name'], $search)) {
834
+ unset($themes['inactive'][$k]);
835
+ }
836
+ }
837
+ }
838
+ }
839
+ }else{
840
+ $all_themes = get_themes();
841
+ $themes = array(
842
+ 'active' => array(),
843
+ 'inactive' => array()
844
+ );
845
+
846
+ if (is_array($all_themes) && !empty($all_themes)) {
847
+ $current_theme = get_current_theme();
848
+
849
+ $br_a = 0;
850
+ $br_i = 0;
851
+ foreach ($all_themes as $theme_name => $theme) {
852
+ if ($current_theme == $theme_name) {
853
+ $themes['active'][$br_a]['path'] = $theme['Template'];
854
+ $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
855
+ $themes['active'][$br_a]['version'] = $theme['Version'];
856
+ $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
857
+ $br_a++;
858
+ }
859
+
860
+ if ($current_theme != $theme_name) {
861
+ $themes['inactive'][$br_i]['path'] = $theme['Template'];
862
+ $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
863
+ $themes['inactive'][$br_i]['version'] = $theme['Version'];
864
+ $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
865
+ $br_i++;
866
+ }
867
+
868
+ }
869
+
870
+ if ($search) {
871
+ foreach ($themes['active'] as $k => $theme) {
872
+ if (!stristr($theme['name'], $search)) {
873
+ unset($themes['active'][$k]);
874
+ }
875
+ }
876
+
877
+ foreach ($themes['inactive'] as $k => $theme) {
878
+ if (!stristr($theme['name'], $search)) {
879
+ unset($themes['inactive'][$k]);
880
+ }
881
+ }
882
+ }
883
+ }
884
+
885
+ }
886
+
887
  return $themes;
888
  }
889
+
890
  function edit($args)
891
  {
892
  extract($args);
898
  }
899
  return $return;
900
  }
901
+
902
  function edit_plugins($args)
903
  {
904
  extract($args);
921
  default:
922
  break;
923
  }
924
+
925
  if (is_wp_error($result)) {
926
  $result = array(
927
  'error' => $result->get_error_message()
935
  }
936
  $return[$item['name']] = $result;
937
  }
938
+
939
  return $return;
940
  }
941
+
942
  function edit_themes($args)
943
  {
944
  extract($args);
954
  default:
955
  break;
956
  }
957
+
958
  if (is_wp_error($result)) {
959
  $result = array(
960
  'error' => $result->get_error_message()
968
  }
969
  $return[$item['name']] = $result;
970
  }
971
+
972
  return $return;
973
+
974
  }
975
  }
976
  ?>
lib/dropbox.php CHANGED
@@ -44,7 +44,7 @@ class Dropbox {
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);
@@ -63,7 +63,7 @@ class Dropbox {
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);
@@ -280,4 +280,4 @@ class Dropbox {
280
 
281
  class DropboxException extends Exception {
282
  }
283
- ?>
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<(1024*1024*50)) { //chunk transfer on bigger uploads <50MB
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);
63
  $uploadid=null;
64
  $offset=0;
65
  $ProgressFunction=null;
66
+ while ($data=fread($file_handle,(1024*1024*30))) { // 30MB chunk size
67
  $chunkHandle = fopen('php://memory', 'rw');
68
  fwrite($chunkHandle,$data);
69
  rewind($chunkHandle);
280
 
281
  class DropboxException extends Exception {
282
  }
283
+ ?>
lib/s3.php CHANGED
@@ -1,1967 +1,2325 @@
1
  <?php
2
  /**
3
- * $Id$
4
- *
5
- * Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are met:
9
- *
10
- * - Redistributions of source code must retain the above copyright notice,
11
- * this list of conditions and the following disclaimer.
12
- * - Redistributions in binary form must reproduce the above copyright
13
- * notice, this list of conditions and the following disclaimer in the
14
- * documentation and/or other materials provided with the distribution.
15
- *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
- * POSSIBILITY OF SUCH DAMAGE.
27
- *
28
- * Amazon S3 is a trademark of Amazon.com, Inc. or its affiliates.
29
- */
30
 
31
  /**
32
- * Amazon S3 PHP class
33
- *
34
- * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
35
- * @version 0.5.0-dev
36
- */
37
  class mwpS3
38
  {
39
- // ACL flags
40
- const ACL_PRIVATE = 'private';
41
- const ACL_PUBLIC_READ = 'public-read';
42
- const ACL_PUBLIC_READ_WRITE = 'public-read-write';
43
- const ACL_AUTHENTICATED_READ = 'authenticated-read';
44
-
45
- const STORAGE_CLASS_STANDARD = 'STANDARD';
46
- const STORAGE_CLASS_RRS = 'REDUCED_REDUNDANCY';
47
-
48
- private static $__accessKey = null; // AWS Access key
49
- private static $__secretKey = null; // AWS Secret key
50
- private static $__sslKey = null;
51
-
52
- public static $endpoint = 's3.amazonaws.com';
53
- public static $proxy = null;
54
-
55
- public static $useSSL = false;
56
- public static $useSSLValidation = true;
57
- public static $useExceptions = false;
58
-
59
- // SSL CURL SSL options - only needed if you are experiencing problems with your OpenSSL configuration
60
- public static $sslKey = null;
61
- public static $sslCert = null;
62
- public static $sslCACert = null;
63
-
64
- private static $__signingKeyPairId = null; // AWS Key Pair ID
65
- private static $__signingKeyResource = false; // Key resource, freeSigningKey() must be called to clear it from memory
66
-
67
-
68
- /**
69
- * Constructor - if you're not using the class statically
70
- *
71
- * @param string $accessKey Access key
72
- * @param string $secretKey Secret key
73
- * @param boolean $useSSL Enable SSL
74
- * @return void
75
- */
76
- public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com')
77
- {
78
- if ($accessKey !== null && $secretKey !== null)
79
- self::setAuth($accessKey, $secretKey);
80
- self::$useSSL = $useSSL;
81
- self::$endpoint = $endpoint;
82
- }
83
-
84
-
85
- /**
86
- * Set the sertvice endpoint
87
- *
88
- * @param string $host Hostname
89
- * @return void
90
- */
91
- public function setEndpoint($host)
92
- {
93
- self::$endpoint = $host;
94
- }
95
-
96
- /**
97
- * Set AWS access key and secret key
98
- *
99
- * @param string $accessKey Access key
100
- * @param string $secretKey Secret key
101
- * @return void
102
- */
103
- public static function setAuth($accessKey, $secretKey)
104
- {
105
- self::$__accessKey = $accessKey;
106
- self::$__secretKey = $secretKey;
107
- }
108
-
109
-
110
- /**
111
- * Check if AWS keys have been set
112
- *
113
- * @return boolean
114
- */
115
- public static function hasAuth() {
116
- return (self::$__accessKey !== null && self::$__secretKey !== null);
117
- }
118
-
119
-
120
- /**
121
- * Set SSL on or off
122
- *
123
- * @param boolean $enabled SSL enabled
124
- * @param boolean $validate SSL certificate validation
125
- * @return void
126
- */
127
- public static function setSSL($enabled, $validate = true)
128
- {
129
- self::$useSSL = $enabled;
130
- self::$useSSLValidation = $validate;
131
- }
132
-
133
-
134
- /**
135
- * Set SSL client certificates (experimental)
136
- *
137
- * @param string $sslCert SSL client certificate
138
- * @param string $sslKey SSL client key
139
- * @param string $sslCACert SSL CA cert (only required if you are having problems with your system CA cert)
140
- * @return void
141
- */
142
- public static function setSSLAuth($sslCert = null, $sslKey = null, $sslCACert = null)
143
- {
144
- self::$sslCert = $sslCert;
145
- self::$sslKey = $sslKey;
146
- self::$sslCACert = $sslCACert;
147
- }
148
-
149
-
150
- /**
151
- * Set proxy information
152
- *
153
- * @param string $host Proxy hostname and port (localhost:1234)
154
- * @param string $user Proxy username
155
- * @param string $pass Proxy password
156
- * @param constant $type CURL proxy type
157
- * @return void
158
- */
159
- public static function setProxy($host, $user = null, $pass = null, $type = CURLPROXY_SOCKS5)
160
- {
161
- self::$proxy = array('host' => $host, 'type' => $type, 'user' => null, 'pass' => 'null');
162
- }
163
-
164
-
165
- /**
166
- * Set the error mode to exceptions
167
- *
168
- * @param boolean $enabled Enable exceptions
169
- * @return void
170
- */
171
- public static function setExceptions($enabled = true)
172
- {
173
- self::$useExceptions = $enabled;
174
- }
175
-
176
-
177
- /**
178
- * Set signing key
179
- *
180
- * @param string $keyPairId AWS Key Pair ID
181
- * @param string $signingKey Private Key
182
- * @param boolean $isFile Load private key from file, set to false to load string
183
- * @return boolean
184
- */
185
- public static function setSigningKey($keyPairId, $signingKey, $isFile = true)
186
- {
187
- self::$__signingKeyPairId = $keyPairId;
188
- if ((self::$__signingKeyResource = openssl_pkey_get_private($isFile ?
189
- file_get_contents($signingKey) : $signingKey)) !== false) return true;
190
- self::__triggerError('mwpS3::setSigningKey(): Unable to open load private key: '.$signingKey, __FILE__, __LINE__);
191
- return false;
192
- }
193
-
194
-
195
- /**
196
- * Free signing key from memory, MUST be called if you are using setSigningKey()
197
- *
198
- * @return void
199
- */
200
- public static function freeSigningKey()
201
- {
202
- if (self::$__signingKeyResource !== false)
203
- openssl_free_key(self::$__signingKeyResource);
204
- }
205
-
206
-
207
- /**
208
- * Internal error handler
209
- *
210
- * @internal Internal error handler
211
- * @param string $message Error message
212
- * @param string $file Filename
213
- * @param integer $line Line number
214
- * @param integer $code Error code
215
- * @return void
216
- */
217
- private static function __triggerError($message, $file, $line, $code = 0)
218
- {
219
-
220
- //if (self::$useExceptions)
221
- throw new mwpS3Exception($message, $file, $line, $code);
222
- //else
223
- //trigger_error($message, E_USER_WARNING);
224
- }
225
-
226
-
227
- /**
228
- * Get a list of buckets
229
- *
230
- * @param boolean $detailed Returns detailed bucket list when true
231
- * @return array | false
232
- */
233
- public static function listBuckets($detailed = false)
234
- {
235
- $rest = new mwpS3Request('GET', '', '', self::$endpoint);
236
- $rest = $rest->getResponse();
237
- if ($rest->error === false && $rest->code !== 200)
238
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
239
- if ($rest->error !== false)
240
- {
241
- self::__triggerError(sprintf("mwpS3::listBuckets(): [%s] %s", $rest->error['code'],
242
- $rest->error['message']), __FILE__, __LINE__);
243
- return false;
244
- }
245
- $results = array();
246
- if (!isset($rest->body->Buckets)) return $results;
247
-
248
- if ($detailed)
249
- {
250
- if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
251
- $results['owner'] = array(
252
- 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
253
- );
254
- $results['buckets'] = array();
255
- foreach ($rest->body->Buckets->Bucket as $b)
256
- $results['buckets'][] = array(
257
- 'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
258
- );
259
- } else
260
- foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
261
-
262
- return $results;
263
- }
264
-
265
-
266
- /*
267
- * Get contents for a bucket
268
- *
269
- * If maxKeys is null this method will loop through truncated result sets
270
- *
271
- * @param string $bucket Bucket name
272
- * @param string $prefix Prefix
273
- * @param string $marker Marker (last file listed)
274
- * @param string $maxKeys Max keys (maximum number of keys to return)
275
- * @param string $delimiter Delimiter
276
- * @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
277
- * @return array | false
278
- */
279
- public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false)
280
- {
281
- $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
282
- if ($maxKeys == 0) $maxKeys = null;
283
- if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
284
- if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
285
- if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
286
- if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
287
- $response = $rest->getResponse();
288
- if ($response->error === false && $response->code !== 200)
289
- $response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
290
- if ($response->error !== false)
291
- {
292
- self::__triggerError(sprintf("mwpS3::getBucket(): [%s] %s",
293
- $response->error['code'], $response->error['message']), __FILE__, __LINE__);
294
- return false;
295
- }
296
-
297
- $results = array();
298
-
299
- $nextMarker = null;
300
- if (isset($response->body, $response->body->Contents))
301
- foreach ($response->body->Contents as $c)
302
- {
303
- $results[(string)$c->Key] = array(
304
- 'name' => (string)$c->Key,
305
- 'time' => strtotime((string)$c->LastModified),
306
- 'size' => (int)$c->Size,
307
- 'hash' => substr((string)$c->ETag, 1, -1)
308
- );
309
- $nextMarker = (string)$c->Key;
310
- }
311
-
312
- if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
313
- foreach ($response->body->CommonPrefixes as $c)
314
- $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
315
-
316
- if (isset($response->body, $response->body->IsTruncated) &&
317
- (string)$response->body->IsTruncated == 'false') return $results;
318
-
319
- if (isset($response->body, $response->body->NextMarker))
320
- $nextMarker = (string)$response->body->NextMarker;
321
-
322
- // Loop through truncated results if maxKeys isn't specified
323
- if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
324
- do
325
- {
326
- $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
327
- if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
328
- $rest->setParameter('marker', $nextMarker);
329
- if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
330
-
331
- if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
332
-
333
- if (isset($response->body, $response->body->Contents))
334
- foreach ($response->body->Contents as $c)
335
- {
336
- $results[(string)$c->Key] = array(
337
- 'name' => (string)$c->Key,
338
- 'time' => strtotime((string)$c->LastModified),
339
- 'size' => (int)$c->Size,
340
- 'hash' => substr((string)$c->ETag, 1, -1)
341
- );
342
- $nextMarker = (string)$c->Key;
343
- }
344
-
345
- if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
346
- foreach ($response->body->CommonPrefixes as $c)
347
- $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
348
-
349
- if (isset($response->body, $response->body->NextMarker))
350
- $nextMarker = (string)$response->body->NextMarker;
351
-
352
- } while ($response !== false && (string)$response->body->IsTruncated == 'true');
353
-
354
- return $results;
355
- }
356
-
357
-
358
- /**
359
- * Put a bucket
360
- *
361
- * @param string $bucket Bucket name
362
- * @param constant $acl ACL flag
363
- * @param string $location Set as "EU" to create buckets hosted in Europe
364
- * @return boolean
365
- */
366
- public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false)
367
- {
368
- $rest = new mwpS3Request('PUT', $bucket, '', self::$endpoint);
369
- $rest->setAmzHeader('x-amz-acl', $acl);
370
-
371
- if ($location !== false)
372
- {
373
- $dom = new DOMDocument;
374
- $createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
375
- $locationConstraint = $dom->createElement('LocationConstraint', $location);
376
- $createBucketConfiguration->appendChild($locationConstraint);
377
- $dom->appendChild($createBucketConfiguration);
378
- $rest->data = $dom->saveXML();
379
- $rest->size = strlen($rest->data);
380
- $rest->setHeader('Content-Type', 'application/xml');
381
- }
382
- $rest = $rest->getResponse();
383
-
384
- if ($rest->error === false && $rest->code !== 200)
385
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
386
- if ($rest->error !== false)
387
- {
388
- self::__triggerError(sprintf("mwpS3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
389
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
390
- return false;
391
- }
392
- return true;
393
- }
394
-
395
-
396
- /**
397
- * Delete an empty bucket
398
- *
399
- * @param string $bucket Bucket name
400
- * @return boolean
401
- */
402
- public static function deleteBucket($bucket)
403
- {
404
- $rest = new mwpS3Request('DELETE', $bucket, '', self::$endpoint);
405
- $rest = $rest->getResponse();
406
- if ($rest->error === false && $rest->code !== 204)
407
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
408
- if ($rest->error !== false)
409
- {
410
- self::__triggerError(sprintf("mwpS3::deleteBucket({$bucket}): [%s] %s",
411
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
412
- return false;
413
- }
414
- return true;
415
- }
416
-
417
-
418
- /**
419
- * Create input info array for putObject()
420
- *
421
- * @param string $file Input file
422
- * @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
423
- * @return array | false
424
- */
425
- public static function inputFile($file, $md5sum = true)
426
- {
427
- if (!file_exists($file) || !is_file($file) || !is_readable($file))
428
- {
429
- self::__triggerError('mwpS3::inputFile(): Unable to open input file: '.$file, __FILE__, __LINE__);
430
- return false;
431
- }
432
- return array('file' => $file, 'size' => filesize($file), 'md5sum' => $md5sum !== false ?
433
- (is_string($md5sum) ? $md5sum : base64_encode(md5_file($file, true))) : '');
434
- }
435
-
436
-
437
- /**
438
- * Create input array info for putObject() with a resource
439
- *
440
- * @param string $resource Input resource to read from
441
- * @param integer $bufferSize Input byte size
442
- * @param string $md5sum MD5 hash to send (optional)
443
- * @return array | false
444
- */
445
- public static function inputResource(&$resource, $bufferSize, $md5sum = '')
446
- {
447
- if (!is_resource($resource) || $bufferSize < 0)
448
- {
449
- self::__triggerError('mwpS3::inputResource(): Invalid resource or buffer size', __FILE__, __LINE__);
450
- return false;
451
- }
452
- $input = array('size' => $bufferSize, 'md5sum' => $md5sum);
453
- $input['fp'] =& $resource;
454
- return $input;
455
- }
456
-
457
-
458
- /**
459
- * Put an object
460
- *
461
- * @param mixed $input Input data
462
- * @param string $bucket Bucket name
463
- * @param string $uri Object URI
464
- * @param constant $acl ACL constant
465
- * @param array $metaHeaders Array of x-amz-meta-* headers
466
- * @param array $requestHeaders Array of request headers or content type as a string
467
- * @param constant $storageClass Storage class constant
468
- * @return boolean
469
- */
470
- public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
471
- {
472
- if ($input === false) return false;
473
- $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
474
-
475
- if (is_string($input)) $input = array(
476
- 'data' => $input, 'size' => strlen($input),
477
- 'md5sum' => base64_encode(md5($input, true))
478
- );
479
-
480
- // Data
481
- if (isset($input['fp']))
482
- $rest->fp =& $input['fp'];
483
- elseif (isset($input['file']))
484
- $rest->fp = @fopen($input['file'], 'rb');
485
- elseif (isset($input['data']))
486
- $rest->data = $input['data'];
487
-
488
- // Content-Length (required)
489
- if (isset($input['size']) && $input['size'] >= 0)
490
- $rest->size = $input['size'];
491
- else {
492
- if (isset($input['file']))
493
- $rest->size = filesize($input['file']);
494
- elseif (isset($input['data']))
495
- $rest->size = strlen($input['data']);
496
- }
497
-
498
- // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
499
- if (is_array($requestHeaders))
500
- foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
501
- elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
502
- $input['type'] = $requestHeaders;
503
-
504
- // Content-Type
505
- if (!isset($input['type']))
506
- {
507
- if (isset($requestHeaders['Content-Type']))
508
- $input['type'] =& $requestHeaders['Content-Type'];
509
- elseif (isset($input['file']))
510
- $input['type'] = self::__getMimeType($input['file']);
511
- else
512
- $input['type'] = 'application/octet-stream';
513
- }
514
-
515
- if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
516
- $rest->setAmzHeader('x-amz-storage-class', $storageClass);
517
-
518
- // We need to post with Content-Length and Content-Type, MD5 is optional
519
- if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false))
520
- {
521
- $rest->setHeader('Content-Type', $input['type']);
522
- if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
523
-
524
- $rest->setAmzHeader('x-amz-acl', $acl);
525
- foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
526
- $rest->getResponse();
527
- } else
528
- $rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
529
-
530
- if ($rest->response->error === false && $rest->response->code !== 200)
531
- $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
532
- if ($rest->response->error !== false)
533
- {
534
- self::__triggerError(sprintf("mwpS3::putObject(): [%s] %s",
535
- $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
536
- return false;
537
- }
538
- return true;
539
- }
540
-
541
-
542
- /**
543
- * Put an object from a file (legacy function)
544
- *
545
- * @param string $file Input file path
546
- * @param string $bucket Bucket name
547
- * @param string $uri Object URI
548
- * @param constant $acl ACL constant
549
- * @param array $metaHeaders Array of x-amz-meta-* headers
550
- * @param string $contentType Content type
551
- * @return boolean
552
- */
553
- public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null)
554
- {
555
- return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
556
- }
557
-
558
-
559
- /**
560
- * Put an object from a string (legacy function)
561
- *
562
- * @param string $string Input data
563
- * @param string $bucket Bucket name
564
- * @param string $uri Object URI
565
- * @param constant $acl ACL constant
566
- * @param array $metaHeaders Array of x-amz-meta-* headers
567
- * @param string $contentType Content type
568
- * @return boolean
569
- */
570
- public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain')
571
- {
572
- return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
573
- }
574
-
575
-
576
- /**
577
- * Get an object
578
- *
579
- * @param string $bucket Bucket name
580
- * @param string $uri Object URI
581
- * @param mixed $saveTo Filename or resource to write to
582
- * @return mixed
583
- */
584
- public static function getObject($bucket, $uri, $saveTo = false)
585
- {
586
- $rest = new mwpS3Request('GET', $bucket, $uri, self::$endpoint);
587
- if ($saveTo !== false)
588
- {
589
- if (is_resource($saveTo))
590
- $rest->fp =& $saveTo;
591
- else
592
- if (($rest->fp = @fopen($saveTo, 'wb')) !== false)
593
- $rest->file = realpath($saveTo);
594
- else
595
- $rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
596
- }
597
- if ($rest->response->error === false) $rest->getResponse();
598
-
599
- if ($rest->response->error === false && $rest->response->code !== 200)
600
- $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
601
- if ($rest->response->error !== false)
602
- {
603
- self::__triggerError(sprintf("mwpS3::getObject({$bucket}, {$uri}): [%s] %s",
604
- $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
605
- return false;
606
- }
607
- return $rest->response;
608
- }
609
-
610
-
611
- /**
612
- * Get object information
613
- *
614
- * @param string $bucket Bucket name
615
- * @param string $uri Object URI
616
- * @param boolean $returnInfo Return response information
617
- * @return mixed | false
618
- */
619
- public static function getObjectInfo($bucket, $uri, $returnInfo = true)
620
- {
621
- $rest = new mwpS3Request('HEAD', $bucket, $uri, self::$endpoint);
622
- $rest = $rest->getResponse();
623
- if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
624
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
625
- if ($rest->error !== false)
626
- {
627
- self::__triggerError(sprintf("mwpS3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
628
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
629
- return false;
630
- }
631
- return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
632
- }
633
-
634
-
635
- /**
636
- * Copy an object
637
- *
638
- * @param string $bucket Source bucket name
639
- * @param string $uri Source object URI
640
- * @param string $bucket Destination bucket name
641
- * @param string $uri Destination object URI
642
- * @param constant $acl ACL constant
643
- * @param array $metaHeaders Optional array of x-amz-meta-* headers
644
- * @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
645
- * @param constant $storageClass Storage class constant
646
- * @return mixed | false
647
- */
648
- public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
649
- {
650
- $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
651
- $rest->setHeader('Content-Length', 0);
652
- foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
653
- foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
654
- if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
655
- $rest->setAmzHeader('x-amz-storage-class', $storageClass);
656
- $rest->setAmzHeader('x-amz-acl', $acl); // Added rawurlencode() for $srcUri (thanks a.yamanoi)
657
- $rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, rawurlencode($srcUri)));
658
- if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
659
- $rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
660
-
661
- $rest = $rest->getResponse();
662
- if ($rest->error === false && $rest->code !== 200)
663
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
664
- if ($rest->error !== false)
665
- {
666
- self::__triggerError(sprintf("mwpS3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
667
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
668
- return false;
669
- }
670
- return isset($rest->body->LastModified, $rest->body->ETag) ? array(
671
- 'time' => strtotime((string)$rest->body->LastModified),
672
- 'hash' => substr((string)$rest->body->ETag, 1, -1)
673
- ) : false;
674
- }
675
-
676
-
677
- /**
678
- * Set logging for a bucket
679
- *
680
- * @param string $bucket Bucket name
681
- * @param string $targetBucket Target bucket (where logs are stored)
682
- * @param string $targetPrefix Log prefix (e,g; domain.com-)
683
- * @return boolean
684
- */
685
- public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null)
686
- {
687
- // The S3 log delivery group has to be added to the target bucket's ACP
688
- if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false)
689
- {
690
- // Only add permissions to the target bucket when they do not exist
691
- $aclWriteSet = false;
692
- $aclReadSet = false;
693
- foreach ($acp['acl'] as $acl)
694
- if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery')
695
- {
696
- if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
697
- elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
698
- }
699
- if (!$aclWriteSet) $acp['acl'][] = array(
700
- 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
701
- );
702
- if (!$aclReadSet) $acp['acl'][] = array(
703
- 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
704
- );
705
- if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
706
- }
707
-
708
- $dom = new DOMDocument;
709
- $bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
710
- $bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
711
- if ($targetBucket !== null)
712
- {
713
- if ($targetPrefix == null) $targetPrefix = $bucket . '-';
714
- $loggingEnabled = $dom->createElement('LoggingEnabled');
715
- $loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
716
- $loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
717
- // TODO: Add TargetGrants?
718
- $bucketLoggingStatus->appendChild($loggingEnabled);
719
- }
720
- $dom->appendChild($bucketLoggingStatus);
721
-
722
- $rest = new mwpS3Request('PUT', $bucket, '', self::$endpoint);
723
- $rest->setParameter('logging', null);
724
- $rest->data = $dom->saveXML();
725
- $rest->size = strlen($rest->data);
726
- $rest->setHeader('Content-Type', 'application/xml');
727
- $rest = $rest->getResponse();
728
- if ($rest->error === false && $rest->code !== 200)
729
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
730
- if ($rest->error !== false)
731
- {
732
- self::__triggerError(sprintf("mwpS3::setBucketLogging({$bucket}, {$uri}): [%s] %s",
733
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
734
- return false;
735
- }
736
- return true;
737
- }
738
-
739
-
740
- /**
741
- * Get logging status for a bucket
742
- *
743
- * This will return false if logging is not enabled.
744
- * Note: To enable logging, you also need to grant write access to the log group
745
- *
746
- * @param string $bucket Bucket name
747
- * @return array | false
748
- */
749
- public static function getBucketLogging($bucket)
750
- {
751
- $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
752
- $rest->setParameter('logging', null);
753
- $rest = $rest->getResponse();
754
- if ($rest->error === false && $rest->code !== 200)
755
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
756
- if ($rest->error !== false)
757
- {
758
- self::__triggerError(sprintf("mwpS3::getBucketLogging({$bucket}): [%s] %s",
759
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
760
- return false;
761
- }
762
- if (!isset($rest->body->LoggingEnabled)) return false; // No logging
763
- return array(
764
- 'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
765
- 'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
766
- );
767
- }
768
-
769
-
770
- /**
771
- * Disable bucket logging
772
- *
773
- * @param string $bucket Bucket name
774
- * @return boolean
775
- */
776
- public static function disableBucketLogging($bucket)
777
- {
778
- return self::setBucketLogging($bucket, null);
779
- }
780
-
781
-
782
- /**
783
- * Get a bucket's location
784
- *
785
- * @param string $bucket Bucket name
786
- * @return string | false
787
- */
788
- public static function getBucketLocation($bucket)
789
- {
790
- $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
791
- $rest->setParameter('location', null);
792
- $rest = $rest->getResponse();
793
- if ($rest->error === false && $rest->code !== 200)
794
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
795
- if ($rest->error !== false)
796
- {
797
- self::__triggerError(sprintf("mwpS3::getBucketLocation({$bucket}): [%s] %s",
798
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
799
- return false;
800
- }
801
- return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
802
- }
803
-
804
-
805
- /**
806
- * Set object or bucket Access Control Policy
807
- *
808
- * @param string $bucket Bucket name
809
- * @param string $uri Object URI
810
- * @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
811
- * @return boolean
812
- */
813
- public static function setAccessControlPolicy($bucket, $uri = '', $acp = array())
814
- {
815
- $dom = new DOMDocument;
816
- $dom->formatOutput = true;
817
- $accessControlPolicy = $dom->createElement('AccessControlPolicy');
818
- $accessControlList = $dom->createElement('AccessControlList');
819
-
820
- // It seems the owner has to be passed along too
821
- $owner = $dom->createElement('Owner');
822
- $owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
823
- $owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
824
- $accessControlPolicy->appendChild($owner);
825
-
826
- foreach ($acp['acl'] as $g)
827
- {
828
- $grant = $dom->createElement('Grant');
829
- $grantee = $dom->createElement('Grantee');
830
- $grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
831
- if (isset($g['id']))
832
- { // CanonicalUser (DisplayName is omitted)
833
- $grantee->setAttribute('xsi:type', 'CanonicalUser');
834
- $grantee->appendChild($dom->createElement('ID', $g['id']));
835
- }
836
- elseif (isset($g['email']))
837
- { // AmazonCustomerByEmail
838
- $grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
839
- $grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
840
- }
841
- elseif ($g['type'] == 'Group')
842
- { // Group
843
- $grantee->setAttribute('xsi:type', 'Group');
844
- $grantee->appendChild($dom->createElement('URI', $g['uri']));
845
- }
846
- $grant->appendChild($grantee);
847
- $grant->appendChild($dom->createElement('Permission', $g['permission']));
848
- $accessControlList->appendChild($grant);
849
- }
850
-
851
- $accessControlPolicy->appendChild($accessControlList);
852
- $dom->appendChild($accessControlPolicy);
853
-
854
- $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
855
- $rest->setParameter('acl', null);
856
- $rest->data = $dom->saveXML();
857
- $rest->size = strlen($rest->data);
858
- $rest->setHeader('Content-Type', 'application/xml');
859
- $rest = $rest->getResponse();
860
- if ($rest->error === false && $rest->code !== 200)
861
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
862
- if ($rest->error !== false)
863
- {
864
- self::__triggerError(sprintf("mwpS3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
865
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
866
- return false;
867
- }
868
- return true;
869
- }
870
-
871
-
872
- /**
873
- * Get object or bucket Access Control Policy
874
- *
875
- * @param string $bucket Bucket name
876
- * @param string $uri Object URI
877
- * @return mixed | false
878
- */
879
- public static function getAccessControlPolicy($bucket, $uri = '')
880
- {
881
- $rest = new mwpS3Request('GET', $bucket, $uri, self::$endpoint);
882
- $rest->setParameter('acl', null);
883
- $rest = $rest->getResponse();
884
- if ($rest->error === false && $rest->code !== 200)
885
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
886
- if ($rest->error !== false)
887
- {
888
- self::__triggerError(sprintf("mwpS3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
889
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
890
- return false;
891
- }
892
-
893
- $acp = array();
894
- if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
895
- $acp['owner'] = array(
896
- 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
897
- );
898
-
899
- if (isset($rest->body->AccessControlList))
900
- {
901
- $acp['acl'] = array();
902
- foreach ($rest->body->AccessControlList->Grant as $grant)
903
- {
904
- foreach ($grant->Grantee as $grantee)
905
- {
906
- if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
907
- $acp['acl'][] = array(
908
- 'type' => 'CanonicalUser',
909
- 'id' => (string)$grantee->ID,
910
- 'name' => (string)$grantee->DisplayName,
911
- 'permission' => (string)$grant->Permission
912
- );
913
- elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
914
- $acp['acl'][] = array(
915
- 'type' => 'AmazonCustomerByEmail',
916
- 'email' => (string)$grantee->EmailAddress,
917
- 'permission' => (string)$grant->Permission
918
- );
919
- elseif (isset($grantee->URI)) // Group
920
- $acp['acl'][] = array(
921
- 'type' => 'Group',
922
- 'uri' => (string)$grantee->URI,
923
- 'permission' => (string)$grant->Permission
924
- );
925
- else continue;
926
- }
927
- }
928
- }
929
- return $acp;
930
- }
931
-
932
-
933
- /**
934
- * Delete an object
935
- *
936
- * @param string $bucket Bucket name
937
- * @param string $uri Object URI
938
- * @return boolean
939
- */
940
- public static function deleteObject($bucket, $uri)
941
- {
942
- $rest = new mwpS3Request('DELETE', $bucket, $uri, self::$endpoint);
943
- $rest = $rest->getResponse();
944
- if ($rest->error === false && $rest->code !== 204)
945
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
946
- if ($rest->error !== false)
947
- {
948
- self::__triggerError(sprintf("mwpS3::deleteObject(): [%s] %s",
949
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
950
- return false;
951
- }
952
- return true;
953
- }
954
-
955
-
956
- /**
957
- * Get a query string authenticated URL
958
- *
959
- * @param string $bucket Bucket name
960
- * @param string $uri Object URI
961
- * @param integer $lifetime Lifetime in seconds
962
- * @param boolean $hostBucket Use the bucket name as the hostname
963
- * @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
964
- * @return string
965
- */
966
- public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false)
967
- {
968
- $expires = time() + $lifetime;
969
- $uri = str_replace('%2F', '/', rawurlencode($uri)); // URI should be encoded (thanks Sean O'Dea)
970
- return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
971
- // $hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
972
- $hostBucket ? $bucket : 's3.amazonaws.com/'.$bucket, $uri, self::$__accessKey, $expires,
973
- urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
974
- }
975
-
976
-
977
- /**
978
- * Get a CloudFront signed policy URL
979
- *
980
- * @param array $policy Policy
981
- * @return string
982
- */
983
- public static function getSignedPolicyURL($policy)
984
- {
985
- $data = json_encode($policy);
986
- $signature = '';
987
- if (!openssl_sign($data, $signature, self::$__signingKeyResource)) return false;
988
-
989
- $encoded = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($data));
990
- $signature = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($signature));
991
-
992
- $url = $policy['Statement'][0]['Resource'] . '?';
993
- foreach (array('Policy' => $encoded, 'Signature' => $signature, 'Key-Pair-Id' => self::$__signingKeyPairId) as $k => $v)
994
- $url .= $k.'='.str_replace('%2F', '/', rawurlencode($v)).'&';
995
- return substr($url, 0, -1);
996
- }
997
-
998
-
999
- /**
1000
- * Get a CloudFront canned policy URL
1001
- *
1002
- * @param string $string URL to sign
1003
- * @param integer $lifetime URL lifetime
1004
- * @return string
1005
- */
1006
- public static function getSignedCannedURL($url, $lifetime)
1007
- {
1008
- return self::getSignedPolicyURL(array(
1009
- 'Statement' => array(
1010
- array('Resource' => $url, 'Condition' => array(
1011
- 'DateLessThan' => array('AWS:EpochTime' => time() + $lifetime)
1012
- ))
1013
- )
1014
- ));
1015
- }
1016
-
1017
-
1018
- /**
1019
- * Get upload POST parameters for form uploads
1020
- *
1021
- * @param string $bucket Bucket name
1022
- * @param string $uriPrefix Object URI prefix
1023
- * @param constant $acl ACL constant
1024
- * @param integer $lifetime Lifetime in seconds
1025
- * @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
1026
- * @param string $successRedirect Redirect URL or 200 / 201 status code
1027
- * @param array $amzHeaders Array of x-amz-meta-* headers
1028
- * @param array $headers Array of request headers or content type as a string
1029
- * @param boolean $flashVars Includes additional "Filename" variable posted by Flash
1030
- * @return object
1031
- */
1032
- public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600,
1033
- $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false)
1034
- {
1035
- // Create policy object
1036
- $policy = new stdClass;
1037
- $policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
1038
- $policy->conditions = array();
1039
- $obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
1040
- $obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
1041
-
1042
- $obj = new stdClass; // 200 for non-redirect uploads
1043
- if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1044
- $obj->success_action_status = (string)$successRedirect;
1045
- else // URL
1046
- $obj->success_action_redirect = $successRedirect;
1047
- array_push($policy->conditions, $obj);
1048
-
1049
- if ($acl !== self::ACL_PUBLIC_READ)
1050
- array_push($policy->conditions, array('eq', '$acl', $acl));
1051
-
1052
- array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
1053
- if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
1054
- foreach (array_keys($headers) as $headerKey)
1055
- array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
1056
- foreach ($amzHeaders as $headerKey => $headerVal)
1057
- {
1058
- $obj = new stdClass;
1059
- $obj->{$headerKey} = (string)$headerVal;
1060
- array_push($policy->conditions, $obj);
1061
- }
1062
- array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
1063
- $policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
1064
-
1065
- // Create parameters
1066
- $params = new stdClass;
1067
- $params->AWSAccessKeyId = self::$__accessKey;
1068
- $params->key = $uriPrefix.'${filename}';
1069
- $params->acl = $acl;
1070
- $params->policy = $policy; unset($policy);
1071
- $params->signature = self::__getHash($params->policy);
1072
- if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1073
- $params->success_action_status = (string)$successRedirect;
1074
- else
1075
- $params->success_action_redirect = $successRedirect;
1076
- foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1077
- foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1078
- return $params;
1079
- }
1080
-
1081
-
1082
- /**
1083
- * Create a CloudFront distribution
1084
- *
1085
- * @param string $bucket Bucket name
1086
- * @param boolean $enabled Enabled (true/false)
1087
- * @param array $cnames Array containing CNAME aliases
1088
- * @param string $comment Use the bucket name as the hostname
1089
- * @param string $defaultRootObject Default root object
1090
- * @param string $originAccessIdentity Origin access identity
1091
- * @param array $trustedSigners Array of trusted signers
1092
- * @return array | false
1093
- */
1094
- public static function createDistribution($bucket, $enabled = true, $cnames = array(), $comment = null, $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1095
- {
1096
- if (!extension_loaded('openssl'))
1097
- {
1098
- self::__triggerError(sprintf("mwpS3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): %s",
1099
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1100
- return false;
1101
- }
1102
- $useSSL = self::$useSSL;
1103
-
1104
- self::$useSSL = true; // CloudFront requires SSL
1105
- $rest = new mwpS3Request('POST', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1106
- $rest->data = self::__getCloudFrontDistributionConfigXML(
1107
- $bucket.'.s3.amazonaws.com',
1108
- $enabled,
1109
- (string)$comment,
1110
- (string)microtime(true),
1111
- $cnames,
1112
- $defaultRootObject,
1113
- $originAccessIdentity,
1114
- $trustedSigners
1115
- );
1116
-
1117
- $rest->size = strlen($rest->data);
1118
- $rest->setHeader('Content-Type', 'application/xml');
1119
- $rest = self::__getCloudFrontResponse($rest);
1120
-
1121
- self::$useSSL = $useSSL;
1122
-
1123
- if ($rest->error === false && $rest->code !== 201)
1124
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1125
- if ($rest->error !== false)
1126
- {
1127
- self::__triggerError(sprintf("mwpS3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): [%s] %s",
1128
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1129
- return false;
1130
- } elseif ($rest->body instanceof SimpleXMLElement)
1131
- return self::__parseCloudFrontDistributionConfig($rest->body);
1132
- return false;
1133
- }
1134
-
1135
-
1136
- /**
1137
- * Get CloudFront distribution info
1138
- *
1139
- * @param string $distributionId Distribution ID from listDistributions()
1140
- * @return array | false
1141
- */
1142
- public static function getDistribution($distributionId)
1143
- {
1144
- if (!extension_loaded('openssl'))
1145
- {
1146
- self::__triggerError(sprintf("mwpS3::getDistribution($distributionId): %s",
1147
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1148
- return false;
1149
- }
1150
- $useSSL = self::$useSSL;
1151
-
1152
- self::$useSSL = true; // CloudFront requires SSL
1153
- $rest = new mwpS3Request('GET', '', '2010-11-01/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
1154
- $rest = self::__getCloudFrontResponse($rest);
1155
-
1156
- self::$useSSL = $useSSL;
1157
-
1158
- if ($rest->error === false && $rest->code !== 200)
1159
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1160
- if ($rest->error !== false)
1161
- {
1162
- self::__triggerError(sprintf("mwpS3::getDistribution($distributionId): [%s] %s",
1163
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1164
- return false;
1165
- }
1166
- elseif ($rest->body instanceof SimpleXMLElement)
1167
- {
1168
- $dist = self::__parseCloudFrontDistributionConfig($rest->body);
1169
- $dist['hash'] = $rest->headers['hash'];
1170
- $dist['id'] = $distributionId;
1171
- return $dist;
1172
- }
1173
- return false;
1174
- }
1175
-
1176
-
1177
- /**
1178
- * Update a CloudFront distribution
1179
- *
1180
- * @param array $dist Distribution array info identical to output of getDistribution()
1181
- * @return array | false
1182
- */
1183
- public static function updateDistribution($dist)
1184
- {
1185
- if (!extension_loaded('openssl'))
1186
- {
1187
- self::__triggerError(sprintf("mwpS3::updateDistribution({$dist['id']}): %s",
1188
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1189
- return false;
1190
- }
1191
-
1192
- $useSSL = self::$useSSL;
1193
-
1194
- self::$useSSL = true; // CloudFront requires SSL
1195
- $rest = new mwpS3Request('PUT', '', '2010-11-01/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
1196
- $rest->data = self::__getCloudFrontDistributionConfigXML(
1197
- $dist['origin'],
1198
- $dist['enabled'],
1199
- $dist['comment'],
1200
- $dist['callerReference'],
1201
- $dist['cnames'],
1202
- $dist['defaultRootObject'],
1203
- $dist['originAccessIdentity'],
1204
- $dist['trustedSigners']
1205
- );
1206
-
1207
- $rest->size = strlen($rest->data);
1208
- $rest->setHeader('If-Match', $dist['hash']);
1209
- $rest = self::__getCloudFrontResponse($rest);
1210
-
1211
- self::$useSSL = $useSSL;
1212
-
1213
- if ($rest->error === false && $rest->code !== 200)
1214
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1215
- if ($rest->error !== false)
1216
- {
1217
- self::__triggerError(sprintf("mwpS3::updateDistribution({$dist['id']}): [%s] %s",
1218
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1219
- return false;
1220
- } else {
1221
- $dist = self::__parseCloudFrontDistributionConfig($rest->body);
1222
- $dist['hash'] = $rest->headers['hash'];
1223
- return $dist;
1224
- }
1225
- return false;
1226
- }
1227
-
1228
-
1229
- /**
1230
- * Delete a CloudFront distribution
1231
- *
1232
- * @param array $dist Distribution array info identical to output of getDistribution()
1233
- * @return boolean
1234
- */
1235
- public static function deleteDistribution($dist)
1236
- {
1237
- if (!extension_loaded('openssl'))
1238
- {
1239
- self::__triggerError(sprintf("mwpS3::deleteDistribution({$dist['id']}): %s",
1240
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1241
- return false;
1242
- }
1243
-
1244
- $useSSL = self::$useSSL;
1245
-
1246
- self::$useSSL = true; // CloudFront requires SSL
1247
- $rest = new mwpS3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
1248
- $rest->setHeader('If-Match', $dist['hash']);
1249
- $rest = self::__getCloudFrontResponse($rest);
1250
-
1251
- self::$useSSL = $useSSL;
1252
-
1253
- if ($rest->error === false && $rest->code !== 204)
1254
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1255
- if ($rest->error !== false)
1256
- {
1257
- self::__triggerError(sprintf("mwpS3::deleteDistribution({$dist['id']}): [%s] %s",
1258
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1259
- return false;
1260
- }
1261
- return true;
1262
- }
1263
-
1264
-
1265
- /**
1266
- * Get a list of CloudFront distributions
1267
- *
1268
- * @return array
1269
- */
1270
- public static function listDistributions()
1271
- {
1272
- if (!extension_loaded('openssl'))
1273
- {
1274
- self::__triggerError(sprintf("mwpS3::listDistributions(): [%s] %s",
1275
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1276
- return false;
1277
- }
1278
-
1279
- $useSSL = self::$useSSL;
1280
- self::$useSSL = true; // CloudFront requires SSL
1281
- $rest = new mwpS3Request('GET', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1282
- $rest = self::__getCloudFrontResponse($rest);
1283
- self::$useSSL = $useSSL;
1284
-
1285
- if ($rest->error === false && $rest->code !== 200)
1286
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1287
- if ($rest->error !== false)
1288
- {
1289
- self::__triggerError(sprintf("mwpS3::listDistributions(): [%s] %s",
1290
- $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1291
- return false;
1292
- }
1293
- elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary))
1294
- {
1295
- $list = array();
1296
- if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated))
1297
- {
1298
- //$info['marker'] = (string)$rest->body->Marker;
1299
- //$info['maxItems'] = (int)$rest->body->MaxItems;
1300
- //$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
1301
- }
1302
- foreach ($rest->body->DistributionSummary as $summary)
1303
- $list[(string)$summary->Id] = self::__parseCloudFrontDistributionConfig($summary);
1304
-
1305
- return $list;
1306
- }
1307
- return array();
1308
- }
1309
-
1310
- /**
1311
- * List CloudFront Origin Access Identities
1312
- *
1313
- * @return array
1314
- */
1315
- public static function listOriginAccessIdentities()
1316
- {
1317
- if (!extension_loaded('openssl'))
1318
- {
1319
- self::__triggerError(sprintf("mwpS3::listOriginAccessIdentities(): [%s] %s",
1320
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1321
- return false;
1322
- }
1323
-
1324
- self::$useSSL = true; // CloudFront requires SSL
1325
- $rest = new mwpS3Request('GET', '', '2010-11-01/origin-access-identity/cloudfront', 'cloudfront.amazonaws.com');
1326
- $rest = self::__getCloudFrontResponse($rest);
1327
- $useSSL = self::$useSSL;
1328
-
1329
- if ($rest->error === false && $rest->code !== 200)
1330
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1331
- if ($rest->error !== false)
1332
- {
1333
- trigger_error(sprintf("mwpS3::listOriginAccessIdentities(): [%s] %s",
1334
- $rest->error['code'], $rest->error['message']), E_USER_WARNING);
1335
- return false;
1336
- }
1337
-
1338
- if (isset($rest->body->CloudFrontOriginAccessIdentitySummary))
1339
- {
1340
- $identities = array();
1341
- foreach ($rest->body->CloudFrontOriginAccessIdentitySummary as $identity)
1342
- if (isset($identity->S3CanonicalUserId))
1343
- $identities[(string)$identity->Id] = array('id' => (string)$identity->Id, 's3CanonicalUserId' => (string)$identity->S3CanonicalUserId);
1344
- return $identities;
1345
- }
1346
- return false;
1347
- }
1348
-
1349
-
1350
- /**
1351
- * Invalidate objects in a CloudFront distribution
1352
- *
1353
- * Thanks to Martin Lindkvist for mwpS3::invalidateDistribution()
1354
- *
1355
- * @param string $distributionId Distribution ID from listDistributions()
1356
- * @param array $paths Array of object paths to invalidate
1357
- * @return boolean
1358
- */
1359
- public static function invalidateDistribution($distributionId, $paths)
1360
- {
1361
- if (!extension_loaded('openssl'))
1362
- {
1363
- self::__triggerError(sprintf("mwpS3::invalidateDistribution(): [%s] %s",
1364
- "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1365
- return false;
1366
- }
1367
-
1368
- $useSSL = self::$useSSL;
1369
- self::$useSSL = true; // CloudFront requires SSL
1370
- $rest = new mwpS3Request('POST', '', '2010-08-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
1371
- $rest->data = self::__getCloudFrontInvalidationBatchXML($paths, (string)microtime(true));
1372
- $rest->size = strlen($rest->data);
1373
- $rest = self::__getCloudFrontResponse($rest);
1374
- self::$useSSL = $useSSL;
1375
-
1376
- if ($rest->error === false && $rest->code !== 201)
1377
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1378
- if ($rest->error !== false)
1379
- {
1380
- trigger_error(sprintf("mwpS3::invalidate('{$distributionId}',{$paths}): [%s] %s",
1381
- $rest->error['code'], $rest->error['message']), E_USER_WARNING);
1382
- return false;
1383
- }
1384
- return true;
1385
- }
1386
-
1387
-
1388
- /**
1389
- * Get a InvalidationBatch DOMDocument
1390
- *
1391
- * @internal Used to create XML in invalidateDistribution()
1392
- * @param array $paths Paths to objects to invalidateDistribution
1393
- * @return string
1394
- */
1395
- private static function __getCloudFrontInvalidationBatchXML($paths, $callerReference = '0') {
1396
- $dom = new DOMDocument('1.0', 'UTF-8');
1397
- $dom->formatOutput = true;
1398
- $invalidationBatch = $dom->createElement('InvalidationBatch');
1399
- foreach ($paths as $path)
1400
- $invalidationBatch->appendChild($dom->createElement('Path', $path));
1401
-
1402
- $invalidationBatch->appendChild($dom->createElement('CallerReference', $callerReference));
1403
- $dom->appendChild($invalidationBatch);
1404
- return $dom->saveXML();
1405
- }
1406
-
1407
-
1408
- /**
1409
- * Get a DistributionConfig DOMDocument
1410
- *
1411
- * http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?PutConfig.html
1412
- *
1413
- * @internal Used to create XML in createDistribution() and updateDistribution()
1414
- * @param string $bucket S3 Origin bucket
1415
- * @param boolean $enabled Enabled (true/false)
1416
- * @param string $comment Comment to append
1417
- * @param string $callerReference Caller reference
1418
- * @param array $cnames Array of CNAME aliases
1419
- * @param string $defaultRootObject Default root object
1420
- * @param string $originAccessIdentity Origin access identity
1421
- * @param array $trustedSigners Array of trusted signers
1422
- * @return string
1423
- */
1424
- private static function __getCloudFrontDistributionConfigXML($bucket, $enabled, $comment, $callerReference = '0', $cnames = array(), $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1425
- {
1426
- $dom = new DOMDocument('1.0', 'UTF-8');
1427
- $dom->formatOutput = true;
1428
- $distributionConfig = $dom->createElement('DistributionConfig');
1429
- $distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2010-11-01/');
1430
-
1431
- $origin = $dom->createElement('S3Origin');
1432
- $origin->appendChild($dom->createElement('DNSName', $bucket));
1433
- if ($originAccessIdentity !== null) $origin->appendChild($dom->createElement('OriginAccessIdentity', $originAccessIdentity));
1434
- $distributionConfig->appendChild($origin);
1435
-
1436
- if ($defaultRootObject !== null) $distributionConfig->appendChild($dom->createElement('DefaultRootObject', $defaultRootObject));
1437
-
1438
- $distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
1439
- foreach ($cnames as $cname)
1440
- $distributionConfig->appendChild($dom->createElement('CNAME', $cname));
1441
- if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
1442
- $distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
1443
-
1444
- $trusted = $dom->createElement('TrustedSigners');
1445
- foreach ($trustedSigners as $id => $type)
1446
- $trusted->appendChild($id !== '' ? $dom->createElement($type, $id) : $dom->createElement($type));
1447
- $distributionConfig->appendChild($trusted);
1448
-
1449
- $dom->appendChild($distributionConfig);
1450
- //var_dump($dom->saveXML());
1451
- return $dom->saveXML();
1452
- }
1453
-
1454
-
1455
- /**
1456
- * Parse a CloudFront distribution config
1457
- *
1458
- * See http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?GetDistribution.html
1459
- *
1460
- * @internal Used to parse the CloudFront DistributionConfig node to an array
1461
- * @param object &$node DOMNode
1462
- * @return array
1463
- */
1464
- private static function __parseCloudFrontDistributionConfig(&$node)
1465
- {
1466
- if (isset($node->DistributionConfig))
1467
- return self::__parseCloudFrontDistributionConfig($node->DistributionConfig);
1468
-
1469
- $dist = array();
1470
- if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName))
1471
- {
1472
- $dist['id'] = (string)$node->Id;
1473
- $dist['status'] = (string)$node->Status;
1474
- $dist['time'] = strtotime((string)$node->LastModifiedTime);
1475
- $dist['domain'] = (string)$node->DomainName;
1476
- }
1477
-
1478
- if (isset($node->CallerReference))
1479
- $dist['callerReference'] = (string)$node->CallerReference;
1480
-
1481
- if (isset($node->Enabled))
1482
- $dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
1483
-
1484
- if (isset($node->S3Origin))
1485
- {
1486
- if (isset($node->S3Origin->DNSName))
1487
- $dist['origin'] = (string)$node->S3Origin->DNSName;
1488
-
1489
- $dist['originAccessIdentity'] = isset($node->S3Origin->OriginAccessIdentity) ?
1490
- (string)$node->S3Origin->OriginAccessIdentity : null;
1491
- }
1492
-
1493
- $dist['defaultRootObject'] = isset($node->DefaultRootObject) ? (string)$node->DefaultRootObject : null;
1494
-
1495
- $dist['cnames'] = array();
1496
- if (isset($node->CNAME))
1497
- foreach ($node->CNAME as $cname)
1498
- $dist['cnames'][(string)$cname] = (string)$cname;
1499
-
1500
- $dist['trustedSigners'] = array();
1501
- if (isset($node->TrustedSigners))
1502
- foreach ($node->TrustedSigners as $signer)
1503
- {
1504
- if (isset($signer->Self))
1505
- $dist['trustedSigners'][''] = 'Self';
1506
- elseif (isset($signer->KeyPairId))
1507
- $dist['trustedSigners'][(string)$signer->KeyPairId] = 'KeyPairId';
1508
- elseif (isset($signer->AwsAccountNumber))
1509
- $dist['trustedSigners'][(string)$signer->AwsAccountNumber] = 'AwsAccountNumber';
1510
- }
1511
-
1512
- $dist['comment'] = isset($node->Comment) ? (string)$node->Comment : null;
1513
- return $dist;
1514
- }
1515
-
1516
-
1517
- /**
1518
- * Grab CloudFront response
1519
- *
1520
- * @internal Used to parse the CloudFront S3Request::getResponse() output
1521
- * @param object &$rest S3Request instance
1522
- * @return object
1523
- */
1524
- private static function __getCloudFrontResponse(&$rest)
1525
- {
1526
- $rest->getResponse();
1527
- if ($rest->response->error === false && isset($rest->response->body) &&
1528
- is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml')
1529
- {
1530
- $rest->response->body = simplexml_load_string($rest->response->body);
1531
- // Grab CloudFront errors
1532
- if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
1533
- $rest->response->body->Error->Message))
1534
- {
1535
- $rest->response->error = array(
1536
- 'code' => (string)$rest->response->body->Error->Code,
1537
- 'message' => (string)$rest->response->body->Error->Message
1538
- );
1539
- unset($rest->response->body);
1540
- }
1541
- }
1542
- return $rest->response;
1543
- }
1544
-
1545
-
1546
- /**
1547
- * Get MIME type for file
1548
- *
1549
- * @internal Used to get mime types
1550
- * @param string &$file File path
1551
- * @return string
1552
- */
1553
- public static function __getMimeType(&$file)
1554
- {
1555
- $type = false;
1556
- // Fileinfo documentation says fileinfo_open() will use the
1557
- // MAGIC env var for the magic file
1558
- if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
1559
- ($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false)
1560
- {
1561
- if (($type = finfo_file($finfo, $file)) !== false)
1562
- {
1563
- // Remove the charset and grab the last content-type
1564
- $type = explode(' ', str_replace('; charset=', ';charset=', $type));
1565
- $type = array_pop($type);
1566
- $type = explode(';', $type);
1567
- $type = trim(array_shift($type));
1568
- }
1569
- finfo_close($finfo);
1570
-
1571
- // If anyone is still using mime_content_type()
1572
- } elseif (function_exists('mime_content_type'))
1573
- $type = trim(mime_content_type($file));
1574
-
1575
- if ($type !== false && strlen($type) > 0) return $type;
1576
-
1577
- // Otherwise do it the old fashioned way
1578
- static $exts = array(
1579
- 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
1580
- 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
1581
- 'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
1582
- 'zip' => 'application/zip', 'gz' => 'application/x-gzip',
1583
- 'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
1584
- 'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
1585
- 'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
1586
- 'css' => 'text/css', 'js' => 'text/javascript',
1587
- 'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
1588
- 'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
1589
- 'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
1590
- 'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
1591
- );
1592
- $ext = strtolower(pathInfo($file, PATHINFO_EXTENSION));
1593
- return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
1594
- }
1595
-
1596
-
1597
- /**
1598
- * Generate the auth string: "AWS AccessKey:Signature"
1599
- *
1600
- * @internal Used by S3Request::getResponse()
1601
- * @param string $string String to sign
1602
- * @return string
1603
- */
1604
- public static function __getSignature($string)
1605
- {
1606
- return 'AWS '.self::$__accessKey.':'.self::__getHash($string);
1607
- }
1608
-
1609
-
1610
- /**
1611
- * Creates a HMAC-SHA1 hash
1612
- *
1613
- * This uses the hash extension if loaded
1614
- *
1615
- * @internal Used by __getSignature()
1616
- * @param string $string String to sign
1617
- * @return string
1618
- */
1619
- private static function __getHash($string)
1620
- {
1621
- return base64_encode(extension_loaded('hash') ?
1622
- hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
1623
- (str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
1624
- pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
1625
- (str_repeat(chr(0x36), 64))) . $string)))));
1626
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1627
 
1628
  }
1629
 
 
 
 
 
 
 
1630
  final class mwpS3Request
1631
  {
1632
- private $endpoint, $verb, $bucket, $uri, $resource = '', $parameters = array(),
1633
- $amzHeaders = array(), $headers = array(
1634
- 'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
1635
- );
1636
- public $fp = false, $size = 0, $data = false, $response;
1637
-
1638
-
1639
- /**
1640
- * Constructor
1641
- *
1642
- * @param string $verb Verb
1643
- * @param string $bucket Bucket name
1644
- * @param string $uri Object URI
1645
- * @return mixed
1646
- */
1647
- function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com')
1648
- {
1649
- $this->endpoint = $endpoint;
1650
- $this->verb = $verb;
1651
- $this->bucket = $bucket;
1652
- $this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
1653
-
1654
- //if ($this->bucket !== '')
1655
- // $this->resource = '/'.$this->bucket.$this->uri;
1656
- //else
1657
- // $this->resource = $this->uri;
1658
-
1659
- if ($this->bucket !== '')
1660
- {
1661
- if ($this->__dnsBucketName($this->bucket))
1662
- {
1663
- $this->headers['Host'] = $this->bucket.'.'.$this->endpoint;
1664
- $this->resource = '/'.$this->bucket.$this->uri;
1665
- }
1666
- else
1667
- {
1668
- $this->headers['Host'] = $this->endpoint;
1669
- $this->uri = $this->uri;
1670
- if ($this->bucket !== '') $this->uri = '/'.$this->bucket.$this->uri;
1671
- $this->bucket = '';
1672
- $this->resource = $this->uri;
1673
- }
1674
- }
1675
- else
1676
- {
1677
- $this->headers['Host'] = $this->endpoint;
1678
- $this->resource = $this->uri;
1679
- }
1680
-
1681
-
1682
- $this->headers['Date'] = gmdate('D, d M Y H:i:s T');
1683
- $this->response = new STDClass;
1684
- $this->response->error = false;
1685
- }
1686
-
1687
-
1688
- /**
1689
- * Set request parameter
1690
- *
1691
- * @param string $key Key
1692
- * @param string $value Value
1693
- * @return void
1694
- */
1695
- public function setParameter($key, $value)
1696
- {
1697
- $this->parameters[$key] = $value;
1698
- }
1699
-
1700
-
1701
- /**
1702
- * Set request header
1703
- *
1704
- * @param string $key Key
1705
- * @param string $value Value
1706
- * @return void
1707
- */
1708
- public function setHeader($key, $value)
1709
- {
1710
- $this->headers[$key] = $value;
1711
- }
1712
-
1713
-
1714
- /**
1715
- * Set x-amz-meta-* header
1716
- *
1717
- * @param string $key Key
1718
- * @param string $value Value
1719
- * @return void
1720
- */
1721
- public function setAmzHeader($key, $value)
1722
- {
1723
- $this->amzHeaders[$key] = $value;
1724
- }
1725
-
1726
-
1727
- /**
1728
- * Get the S3 response
1729
- *
1730
- * @return object | false
1731
- */
1732
- public function getResponse()
1733
- {
1734
- $query = '';
1735
- if (sizeof($this->parameters) > 0)
1736
- {
1737
- $query = substr($this->uri, -1) !== '?' ? '?' : '&';
1738
- foreach ($this->parameters as $var => $value)
1739
- if ($value == null || $value == '') $query .= $var.'&';
1740
- // Parameters should be encoded (thanks Sean O'Dea)
1741
- else $query .= $var.'='.rawurlencode($value).'&';
1742
- $query = substr($query, 0, -1);
1743
- $this->uri .= $query;
1744
-
1745
- if (array_key_exists('acl', $this->parameters) ||
1746
- array_key_exists('location', $this->parameters) ||
1747
- array_key_exists('torrent', $this->parameters) ||
1748
- array_key_exists('website', $this->parameters) ||
1749
- array_key_exists('logging', $this->parameters))
1750
- $this->resource .= $query;
1751
- }
1752
- $url = (mwpS3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
1753
-
1754
- //var_dump('bucket: ' . $this->bucket, 'uri: ' . $this->uri, 'resource: ' . $this->resource, 'url: ' . $url);
1755
-
1756
- // Basic setup
1757
- $curl = curl_init();
1758
- curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
1759
- curl_setopt($curl,CURLOPT_TIMEOUT,600);
1760
- if (mwpS3::$useSSL)
1761
- {
1762
- // SSL Validation can now be optional for those with broken OpenSSL installations
1763
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, mwpS3::$useSSLValidation ? 1 : 0);
1764
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, mwpS3::$useSSLValidation ? 1 : 0);
1765
-
1766
- if (mwpS3::$sslKey !== null) curl_setopt($curl, CURLOPT_SSLKEY, mwpS3::$sslKey);
1767
- if (mwpS3::$sslCert !== null) curl_setopt($curl, CURLOPT_SSLCERT, mwpS3::$sslCert);
1768
- if (mwpS3::$sslCACert !== null) curl_setopt($curl, CURLOPT_CAINFO, mwpS3::$sslCACert);
1769
- }
1770
-
1771
- curl_setopt($curl, CURLOPT_URL, $url);
1772
-
1773
- if (mwpS3::$proxy != null && isset(mwpS3::$proxy['host']))
1774
- {
1775
- curl_setopt($curl, CURLOPT_PROXY, mwpS3::$proxy['host']);
1776
- curl_setopt($curl, CURLOPT_PROXYTYPE, mwpS3::$proxy['type']);
1777
- if (isset(mwpS3::$proxy['user'], mwpS3::$proxy['pass']) && $proxy['user'] != null && $proxy['pass'] != null)
1778
- curl_setopt($curl, CURLOPT_PROXYUSERPWD, sprintf('%s:%s', mwpS3::$proxy['user'], mwpS3::$proxy['pass']));
1779
- }
1780
-
1781
- // Headers
1782
- $headers = array(); $amz = array();
1783
- foreach ($this->amzHeaders as $header => $value)
1784
- if (strlen($value) > 0) $headers[] = $header.': '.$value;
1785
- foreach ($this->headers as $header => $value)
1786
- if (strlen($value) > 0) $headers[] = $header.': '.$value;
1787
-
1788
- // Collect AMZ headers for signature
1789
- foreach ($this->amzHeaders as $header => $value)
1790
- if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
1791
-
1792
- // AMZ headers must be sorted
1793
- if (sizeof($amz) > 0)
1794
- {
1795
- sort($amz);
1796
- $amz = "\n".implode("\n", $amz);
1797
- } else $amz = '';
1798
-
1799
- if (mwpS3::hasAuth())
1800
- {
1801
- // Authorization string (CloudFront stringToSign should only contain a date)
1802
- if ($this->headers['Host'] == 'cloudfront.amazonaws.com')
1803
- $headers[] = 'Authorization: ' . mwpS3::__getSignature($this->headers['Date']);
1804
- else
1805
- {
1806
- $headers[] = 'Authorization: ' . mwpS3::__getSignature(
1807
- $this->verb."\n".
1808
- $this->headers['Content-MD5']."\n".
1809
- $this->headers['Content-Type']."\n".
1810
- $this->headers['Date'].$amz."\n".
1811
- $this->resource
1812
- );
1813
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1814
  }
1815
 
1816
- curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
1817
- curl_setopt($curl, CURLOPT_HEADER, false);
1818
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
1819
- curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
1820
- curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
1821
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
1822
-
1823
- // Request types
1824
- switch ($this->verb)
1825
- {
1826
- case 'GET': break;
1827
- case 'PUT': case 'POST': // POST only used for CloudFront
1828
- if ($this->fp !== false)
1829
- {
1830
- curl_setopt($curl, CURLOPT_PUT, true);
1831
- curl_setopt($curl, CURLOPT_INFILE, $this->fp);
1832
- if ($this->size >= 0)
1833
- curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
1834
- }
1835
- elseif ($this->data !== false)
1836
- {
1837
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
1838
- curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
1839
- }
1840
- else
1841
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
1842
- break;
1843
- case 'HEAD':
1844
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
1845
- curl_setopt($curl, CURLOPT_NOBODY, true);
1846
- break;
1847
- case 'DELETE':
1848
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
1849
- break;
1850
- default: break;
1851
- }
1852
-
1853
- // Execute, grab errors
1854
- if (curl_exec($curl))
1855
- $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
1856
- else
1857
- $this->response->error = array(
1858
- 'code' => curl_errno($curl),
1859
- 'message' => curl_error($curl),
1860
- 'resource' => $this->resource
1861
- );
1862
-
1863
- @curl_close($curl);
1864
-
1865
- // Parse body into XML
1866
- if ($this->response->error === false && isset($this->response->headers['type']) &&
1867
- $this->response->headers['type'] == 'application/xml' && isset($this->response->body))
1868
- {
1869
- $this->response->body = simplexml_load_string($this->response->body);
1870
-
1871
- // Grab S3 errors
1872
- if (!in_array($this->response->code, array(200, 204, 206)) &&
1873
- isset($this->response->body->Code, $this->response->body->Message))
1874
- {
1875
- $this->response->error = array(
1876
- 'code' => (string)$this->response->body->Code,
1877
- 'message' => (string)$this->response->body->Message
1878
- );
1879
- if (isset($this->response->body->Resource))
1880
- $this->response->error['resource'] = (string)$this->response->body->Resource;
1881
- unset($this->response->body);
1882
- }
1883
- }
1884
-
1885
- // Clean up file resources
1886
- if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
1887
-
1888
- return $this->response;
1889
- }
1890
-
1891
-
1892
- /**
1893
- * CURL write callback
1894
- *
1895
- * @param resource &$curl CURL resource
1896
- * @param string &$data Data
1897
- * @return integer
1898
- */
1899
- private function __responseWriteCallback(&$curl, &$data)
1900
- {
1901
- if (in_array($this->response->code, array(200, 206)) && $this->fp !== false)
1902
- return fwrite($this->fp, $data);
1903
- else
1904
- $this->response->body .= $data;
1905
- return strlen($data);
1906
- }
1907
-
1908
-
1909
- /**
1910
- * Check DNS conformity
1911
- *
1912
- * @param string $bucket Bucket name
1913
- * @return boolean
1914
- */
1915
- private function __dnsBucketName($bucket)
1916
- {
1917
- if (strlen($bucket) > 63 || !preg_match("/[^a-z0-9\.-]/", $bucket)) return false;
1918
- if (strstr($bucket, '-.') !== false) return false;
1919
- if (strstr($bucket, '..') !== false) return false;
1920
- if (!preg_match("/^[0-9a-z]/", $bucket)) return false;
1921
- if (!preg_match("/[0-9a-z]$/", $bucket)) return false;
1922
- return true;
1923
- }
1924
-
1925
-
1926
- /**
1927
- * CURL header callback
1928
- *
1929
- * @param resource &$curl CURL resource
1930
- * @param string &$data Data
1931
- * @return integer
1932
- */
1933
- private function __responseHeaderCallback(&$curl, &$data)
1934
- {
1935
- if (($strlen = strlen($data)) <= 2) return $strlen;
1936
- if (substr($data, 0, 4) == 'HTTP')
1937
- $this->response->code = (int)substr($data, 9, 3);
1938
- else
1939
- {
1940
- $data = trim($data);
1941
- if (strpos($data, ': ') === false) return $strlen;
1942
- list($header, $value) = explode(': ', $data, 2);
1943
- if ($header == 'Last-Modified')
1944
- $this->response->headers['time'] = strtotime($value);
1945
- elseif ($header == 'Content-Length')
1946
- $this->response->headers['size'] = (int)$value;
1947
- elseif ($header == 'Content-Type')
1948
- $this->response->headers['type'] = $value;
1949
- elseif ($header == 'ETag')
1950
- $this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
1951
- elseif (preg_match('/^x-amz-meta-.*$/', $header))
1952
- $this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
1953
- }
1954
- return $strlen;
1955
- }
1956
 
1957
  }
1958
 
 
 
 
 
 
 
 
1959
  class mwpS3Exception extends Exception {
1960
- function __construct($message, $file, $line, $code = 0)
1961
- {
1962
- parent::__construct($message, $code);
1963
- $this->file = $file;
1964
- $this->line = $line;
1965
- }
 
 
 
 
 
 
 
 
1966
  }
1967
-
1
  <?php
2
  /**
3
+ * $Id$
4
+ *
5
+ * Copyright (c) 2013, Donovan Schönknecht. All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * - Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ * - Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Amazon S3 is a trademark of Amazon.com, Inc. or its affiliates.
29
+ */
30
 
31
  /**
32
+ * Amazon S3 PHP class
33
+ *
34
+ * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
35
+ * @version 0.5.1-dev
36
+ */
37
  class mwpS3
38
  {
39
+ // ACL flags
40
+ const ACL_PRIVATE = 'private';
41
+ const ACL_PUBLIC_READ = 'public-read';
42
+ const ACL_PUBLIC_READ_WRITE = 'public-read-write';
43
+ const ACL_AUTHENTICATED_READ = 'authenticated-read';
44
+
45
+ const STORAGE_CLASS_STANDARD = 'STANDARD';
46
+ const STORAGE_CLASS_RRS = 'REDUCED_REDUNDANCY';
47
+
48
+ const SSE_NONE = '';
49
+ const SSE_AES256 = 'AES256';
50
+
51
+ /**
52
+ * The AWS Access key
53
+ *
54
+ * @var string
55
+ * @access private
56
+ * @static
57
+ */
58
+ private static $__accessKey = null;
59
+
60
+ /**
61
+ * AWS Secret Key
62
+ *
63
+ * @var string
64
+ * @access private
65
+ * @static
66
+ */
67
+ private static $__secretKey = null;
68
+
69
+ /**
70
+ * SSL Client key
71
+ *
72
+ * @var string
73
+ * @access private
74
+ * @static
75
+ */
76
+ private static $__sslKey = null;
77
+
78
+ /**
79
+ * AWS URI
80
+ *
81
+ * @var string
82
+ * @acess public
83
+ * @static
84
+ */
85
+ public static $endpoint = 's3.amazonaws.com';
86
+
87
+ /**
88
+ * Proxy information
89
+ *
90
+ * @var null|array
91
+ * @access public
92
+ * @static
93
+ */
94
+ public static $proxy = null;
95
+
96
+ /**
97
+ * Connect using SSL?
98
+ *
99
+ * @var bool
100
+ * @access public
101
+ * @static
102
+ */
103
+ public static $useSSL = false;
104
+
105
+ /**
106
+ * Use SSL validation?
107
+ *
108
+ * @var bool
109
+ * @access public
110
+ * @static
111
+ */
112
+ public static $useSSLValidation = true;
113
+
114
+ /**
115
+ * Use PHP exceptions?
116
+ *
117
+ * @var bool
118
+ * @access public
119
+ * @static
120
+ */
121
+ public static $useExceptions = false;
122
+
123
+ /**
124
+ * Time offset applied to time()
125
+ * @access private
126
+ * @static
127
+ */
128
+ private static $__timeOffset = 0;
129
+
130
+ /**
131
+ * SSL client key
132
+ *
133
+ * @var bool
134
+ * @access public
135
+ * @static
136
+ */
137
+ public static $sslKey = null;
138
+
139
+ /**
140
+ * SSL client certfificate
141
+ *
142
+ * @var string
143
+ * @acess public
144
+ * @static
145
+ */
146
+ public static $sslCert = null;
147
+
148
+ /**
149
+ * SSL CA cert (only required if you are having problems with your system CA cert)
150
+ *
151
+ * @var string
152
+ * @access public
153
+ * @static
154
+ */
155
+ public static $sslCACert = null;
156
+
157
+ /**
158
+ * AWS Key Pair ID
159
+ *
160
+ * @var string
161
+ * @access private
162
+ * @static
163
+ */
164
+ private static $__signingKeyPairId = null;
165
+
166
+ /**
167
+ * Key resource, freeSigningKey() must be called to clear it from memory
168
+ *
169
+ * @var bool
170
+ * @access private
171
+ * @static
172
+ */
173
+ private static $__signingKeyResource = false;
174
+
175
+
176
+ /**
177
+ * Constructor - if you're not using the class statically
178
+ *
179
+ * @param string $accessKey Access key
180
+ * @param string $secretKey Secret key
181
+ * @param boolean $useSSL Enable SSL
182
+ * @param string $endpoint Amazon URI
183
+ * @return void
184
+ */
185
+ public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com')
186
+ {
187
+ if ($accessKey !== null && $secretKey !== null)
188
+ self::setAuth($accessKey, $secretKey);
189
+ self::$useSSL = $useSSL;
190
+ self::$endpoint = $endpoint;
191
+ }
192
+
193
+
194
+ /**
195
+ * Set the service endpoint
196
+ *
197
+ * @param string $host Hostname
198
+ * @return void
199
+ */
200
+ public function setEndpoint($host)
201
+ {
202
+ self::$endpoint = $host;
203
+ }
204
+
205
+ /**
206
+ * Set AWS access key and secret key
207
+ *
208
+ * @param string $accessKey Access key
209
+ * @param string $secretKey Secret key
210
+ * @return void
211
+ */
212
+ public static function setAuth($accessKey, $secretKey)
213
+ {
214
+ self::$__accessKey = $accessKey;
215
+ self::$__secretKey = $secretKey;
216
+ }
217
+
218
+
219
+ /**
220
+ * Check if AWS keys have been set
221
+ *
222
+ * @return boolean
223
+ */
224
+ public static function hasAuth() {
225
+ return (self::$__accessKey !== null && self::$__secretKey !== null);
226
+ }
227
+
228
+
229
+ /**
230
+ * Set SSL on or off
231
+ *
232
+ * @param boolean $enabled SSL enabled
233
+ * @param boolean $validate SSL certificate validation
234
+ * @return void
235
+ */
236
+ public static function setSSL($enabled, $validate = true)
237
+ {
238
+ self::$useSSL = $enabled;
239
+ self::$useSSLValidation = $validate;
240
+ }
241
+
242
+
243
+ /**
244
+ * Set SSL client certificates (experimental)
245
+ *
246
+ * @param string $sslCert SSL client certificate
247
+ * @param string $sslKey SSL client key
248
+ * @param string $sslCACert SSL CA cert (only required if you are having problems with your system CA cert)
249
+ * @return void
250
+ */
251
+ public static function setSSLAuth($sslCert = null, $sslKey = null, $sslCACert = null)
252
+ {
253
+ self::$sslCert = $sslCert;
254
+ self::$sslKey = $sslKey;
255
+ self::$sslCACert = $sslCACert;
256
+ }
257
+
258
+
259
+ /**
260
+ * Set proxy information
261
+ *
262
+ * @param string $host Proxy hostname and port (localhost:1234)
263
+ * @param string $user Proxy username
264
+ * @param string $pass Proxy password
265
+ * @param constant $type CURL proxy type
266
+ * @return void
267
+ */
268
+ public static function setProxy($host, $user = null, $pass = null, $type = CURLPROXY_SOCKS5)
269
+ {
270
+ self::$proxy = array('host' => $host, 'type' => $type, 'user' => $user, 'pass' => $pass);
271
+ }
272
+
273
+
274
+ /**
275
+ * Set the error mode to exceptions
276
+ *
277
+ * @param boolean $enabled Enable exceptions
278
+ * @return void
279
+ */
280
+ public static function setExceptions($enabled = true)
281
+ {
282
+ self::$useExceptions = $enabled;
283
+ }
284
+
285
+
286
+ /**
287
+ * Set signing key
288
+ *
289
+ * @param string $keyPairId AWS Key Pair ID
290
+ * @param string $signingKey Private Key
291
+ * @param boolean $isFile Load private key from file, set to false to load string
292
+ * @return boolean
293
+ */
294
+ public static function setSigningKey($keyPairId, $signingKey, $isFile = true)
295
+ {
296
+ self::$__signingKeyPairId = $keyPairId;
297
+ if ((self::$__signingKeyResource = openssl_pkey_get_private($isFile ?
298
+ file_get_contents($signingKey) : $signingKey)) !== false) return true;
299
+ self::__triggerError('mwpS3::setSigningKey(): Unable to open load private key: '.$signingKey, __FILE__, __LINE__);
300
+ return false;
301
+ }
302
+
303
+
304
+ /**
305
+ * Free signing key from memory, MUST be called if you are using setSigningKey()
306
+ *
307
+ * @return void
308
+ */
309
+ public static function freeSigningKey()
310
+ {
311
+ if (self::$__signingKeyResource !== false)
312
+ openssl_free_key(self::$__signingKeyResource);
313
+ }
314
+
315
+
316
+ /**
317
+ * Internal error handler
318
+ *
319
+ * @internal Internal error handler
320
+ * @param string $message Error message
321
+ * @param string $file Filename
322
+ * @param integer $line Line number
323
+ * @param integer $code Error code
324
+ * @return void
325
+ */
326
+ private static function __triggerError($message, $file, $line, $code = 0)
327
+ {
328
+
329
+ //if (self::$useExceptions)
330
+ throw new mwpS3Exception($message, $file, $line, $code);
331
+ //else
332
+ //trigger_error($message, E_USER_WARNING);
333
+ }
334
+
335
+
336
+ /**
337
+ * Get a list of buckets
338
+ *
339
+ * @param boolean $detailed Returns detailed bucket list when true
340
+ * @return array | false
341
+ */
342
+ public static function listBuckets($detailed = false)
343
+ {
344
+ $rest = new mwpS3Request('GET', '', '', self::$endpoint);
345
+ $rest = $rest->getResponse();
346
+ if ($rest->error === false && $rest->code !== 200)
347
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
348
+ if ($rest->error !== false)
349
+ {
350
+ self::__triggerError(sprintf("mwpS3::listBuckets(): [%s] %s", $rest->error['code'],
351
+ $rest->error['message']), __FILE__, __LINE__);
352
+ return false;
353
+ }
354
+ $results = array();
355
+ if (!isset($rest->body->Buckets)) return $results;
356
+
357
+ if ($detailed)
358
+ {
359
+ if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
360
+ $results['owner'] = array(
361
+ 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
362
+ );
363
+ $results['buckets'] = array();
364
+ foreach ($rest->body->Buckets->Bucket as $b)
365
+ $results['buckets'][] = array(
366
+ 'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
367
+ );
368
+ } else
369
+ foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
370
+
371
+ return $results;
372
+ }
373
+
374
+
375
+ /**
376
+ * Get contents for a bucket
377
+ *
378
+ * If maxKeys is null this method will loop through truncated result sets
379
+ *
380
+ * @param string $bucket Bucket name
381
+ * @param string $prefix Prefix
382
+ * @param string $marker Marker (last file listed)
383
+ * @param string $maxKeys Max keys (maximum number of keys to return)
384
+ * @param string $delimiter Delimiter
385
+ * @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
386
+ * @return array | false
387
+ */
388
+ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false)
389
+ {
390
+ $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
391
+ if ($maxKeys == 0) $maxKeys = null;
392
+ if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
393
+ if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
394
+ if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
395
+ if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
396
+ $response = $rest->getResponse();
397
+ if ($response->error === false && $response->code !== 200)
398
+ $response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
399
+ if ($response->error !== false)
400
+ {
401
+ self::__triggerError(sprintf("mwpS3::getBucket(): [%s] %s",
402
+ $response->error['code'], $response->error['message']), __FILE__, __LINE__);
403
+ return false;
404
+ }
405
+
406
+ $results = array();
407
+
408
+ $nextMarker = null;
409
+ if (isset($response->body, $response->body->Contents))
410
+ foreach ($response->body->Contents as $c)
411
+ {
412
+ $results[(string)$c->Key] = array(
413
+ 'name' => (string)$c->Key,
414
+ 'time' => strtotime((string)$c->LastModified),
415
+ 'size' => (int)$c->Size,
416
+ 'hash' => substr((string)$c->ETag, 1, -1)
417
+ );
418
+ $nextMarker = (string)$c->Key;
419
+ }
420
+
421
+ if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
422
+ foreach ($response->body->CommonPrefixes as $c)
423
+ $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
424
+
425
+ if (isset($response->body, $response->body->IsTruncated) &&
426
+ (string)$response->body->IsTruncated == 'false') return $results;
427
+
428
+ if (isset($response->body, $response->body->NextMarker))
429
+ $nextMarker = (string)$response->body->NextMarker;
430
+
431
+ // Loop through truncated results if maxKeys isn't specified
432
+ if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
433
+ do
434
+ {
435
+ $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
436
+ if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
437
+ $rest->setParameter('marker', $nextMarker);
438
+ if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
439
+
440
+ if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
441
+
442
+ if (isset($response->body, $response->body->Contents))
443
+ foreach ($response->body->Contents as $c)
444
+ {
445
+ $results[(string)$c->Key] = array(
446
+ 'name' => (string)$c->Key,
447
+ 'time' => strtotime((string)$c->LastModified),
448
+ 'size' => (int)$c->Size,
449
+ 'hash' => substr((string)$c->ETag, 1, -1)
450
+ );
451
+ $nextMarker = (string)$c->Key;
452
+ }
453
+
454
+ if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
455
+ foreach ($response->body->CommonPrefixes as $c)
456
+ $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
457
+
458
+ if (isset($response->body, $response->body->NextMarker))
459
+ $nextMarker = (string)$response->body->NextMarker;
460
+
461
+ } while ($response !== false && (string)$response->body->IsTruncated == 'true');
462
+
463
+ return $results;
464
+ }
465
+
466
+
467
+ /**
468
+ * Put a bucket
469
+ *
470
+ * @param string $bucket Bucket name
471
+ * @param constant $acl ACL flag
472
+ * @param string $location Set as "EU" to create buckets hosted in Europe
473
+ * @return boolean
474
+ */
475
+ public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false)
476
+ {
477
+ $rest = new mwpS3Request('PUT', $bucket, '', self::$endpoint);
478
+ $rest->setAmzHeader('x-amz-acl', $acl);
479
+
480
+ if ($location !== false)
481
+ {
482
+ $dom = new DOMDocument;
483
+ $createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
484
+ $locationConstraint = $dom->createElement('LocationConstraint', $location);
485
+ $createBucketConfiguration->appendChild($locationConstraint);
486
+ $dom->appendChild($createBucketConfiguration);
487
+ $rest->data = $dom->saveXML();
488
+ $rest->size = strlen($rest->data);
489
+ $rest->setHeader('Content-Type', 'application/xml');
490
+ }
491
+ $rest = $rest->getResponse();
492
+
493
+ if ($rest->error === false && $rest->code !== 200)
494
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
495
+ if ($rest->error !== false)
496
+ {
497
+ self::__triggerError(sprintf("mwpS3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
498
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
499
+ return false;
500
+ }
501
+ return true;
502
+ }
503
+
504
+
505
+ /**
506
+ * Delete an empty bucket
507
+ *
508
+ * @param string $bucket Bucket name
509
+ * @return boolean
510
+ */
511
+ public static function deleteBucket($bucket)
512
+ {
513
+ $rest = new mwpS3Request('DELETE', $bucket, '', self::$endpoint);
514
+ $rest = $rest->getResponse();
515
+ if ($rest->error === false && $rest->code !== 204)
516
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
517
+ if ($rest->error !== false)
518
+ {
519
+ self::__triggerError(sprintf("mwpS3::deleteBucket({$bucket}): [%s] %s",
520
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
521
+ return false;
522
+ }
523
+ return true;
524
+ }
525
+
526
+
527
+ /**
528
+ * Create input info array for putObject()
529
+ *
530
+ * @param string $file Input file
531
+ * @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
532
+ * @return array | false
533
+ */
534
+ public static function inputFile($file, $md5sum = true)
535
+ {
536
+ if (!file_exists($file) || !is_file($file) || !is_readable($file))
537
+ {
538
+ self::__triggerError('mwpS3::inputFile(): Unable to open input file: '.$file, __FILE__, __LINE__);
539
+ return false;
540
+ }
541
+ return array('file' => $file, 'size' => filesize($file), 'md5sum' => $md5sum !== false ?
542
+ (is_string($md5sum) ? $md5sum : base64_encode(md5_file($file, true))) : '');
543
+ }
544
+
545
+
546
+ /**
547
+ * Create input array info for putObject() with a resource
548
+ *
549
+ * @param string $resource Input resource to read from
550
+ * @param integer $bufferSize Input byte size
551
+ * @param string $md5sum MD5 hash to send (optional)
552
+ * @return array | false
553
+ */
554
+ public static function inputResource(&$resource, $bufferSize = false, $md5sum = '')
555
+ {
556
+ if (!is_resource($resource) || (int)$bufferSize < 0)
557
+ {
558
+ self::__triggerError('mwpS3::inputResource(): Invalid resource or buffer size', __FILE__, __LINE__);
559
+ return false;
560
+ }
561
+
562
+ // Try to figure out the bytesize
563
+ if ($bufferSize === false)
564
+ {
565
+ if (fseek($resource, 0, SEEK_END) < 0 || ($bufferSize = ftell($resource)) === false)
566
+ {
567
+ self::__triggerError('S3::inputResource(): Unable to obtain resource size', __FILE__, __LINE__);
568
+ return false;
569
+ }
570
+ fseek($resource, 0);
571
+ }
572
+
573
+ $input = array('size' => $bufferSize, 'md5sum' => $md5sum);
574
+ $input['fp'] =& $resource;
575
+ return $input;
576
+ }
577
+
578
+
579
+ /**
580
+ * Put an object
581
+ *
582
+ * @param mixed $input Input data
583
+ * @param string $bucket Bucket name
584
+ * @param string $uri Object URI
585
+ * @param constant $acl ACL constant
586
+ * @param array $metaHeaders Array of x-amz-meta-* headers
587
+ * @param array $requestHeaders Array of request headers or content type as a string
588
+ * @param constant $storageClass Storage class constant
589
+ * @param constant $serverSideEncryption Server-side encryption
590
+ * @return boolean
591
+ */
592
+ public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD, $serverSideEncryption = self::SSE_NONE)
593
+ {
594
+ if ($input === false) return false;
595
+ $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
596
+
597
+ if (!is_array($input)) $input = array(
598
+ 'data' => $input, 'size' => strlen($input),
599
+ 'md5sum' => base64_encode(md5($input, true))
600
+ );
601
+
602
+ // Data
603
+ if (isset($input['fp']))
604
+ $rest->fp =& $input['fp'];
605
+ elseif (isset($input['file']))
606
+ $rest->fp = @fopen($input['file'], 'rb');
607
+ elseif (isset($input['data']))
608
+ $rest->data = $input['data'];
609
+
610
+ // Content-Length (required)
611
+ if (isset($input['size']) && $input['size'] >= 0)
612
+ $rest->size = $input['size'];
613
+ else {
614
+ if (isset($input['file']))
615
+ $rest->size = filesize($input['file']);
616
+ elseif (isset($input['data']))
617
+ $rest->size = strlen($input['data']);
618
+ }
619
+
620
+ // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
621
+ if (is_array($requestHeaders))
622
+ foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
623
+ elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
624
+ $input['type'] = $requestHeaders;
625
+
626
+ // Content-Type
627
+ if (!isset($input['type']))
628
+ {
629
+ if (isset($requestHeaders['Content-Type']))
630
+ $input['type'] =& $requestHeaders['Content-Type'];
631
+ elseif (isset($input['file']))
632
+ $input['type'] = self::__getMIMEType($input['file']);
633
+ else
634
+ $input['type'] = 'application/octet-stream';
635
+ }
636
+
637
+ if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
638
+ $rest->setAmzHeader('x-amz-storage-class', $storageClass);
639
+
640
+ if ($serverSideEncryption !== self::SSE_NONE) // Server-side encryption
641
+ $rest->setAmzHeader('x-amz-server-side-encryption', $serverSideEncryption);
642
+
643
+ // We need to post with Content-Length and Content-Type, MD5 is optional
644
+ if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false))
645
+ {
646
+ $rest->setHeader('Content-Type', $input['type']);
647
+ if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
648
+
649
+ $rest->setAmzHeader('x-amz-acl', $acl);
650
+ foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
651
+ $rest->getResponse();
652
+ } else
653
+ $rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
654
+
655
+ if ($rest->response->error === false && $rest->response->code !== 200)
656
+ $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
657
+ if ($rest->response->error !== false)
658
+ {
659
+ self::__triggerError(sprintf("mwpS3::putObject(): [%s] %s",
660
+ $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
661
+ return false;
662
+ }
663
+ return true;
664
+ }
665
+
666
+
667
+ /**
668
+ * Put an object from a file (legacy function)
669
+ *
670
+ * @param string $file Input file path
671
+ * @param string $bucket Bucket name
672
+ * @param string $uri Object URI
673
+ * @param constant $acl ACL constant
674
+ * @param array $metaHeaders Array of x-amz-meta-* headers
675
+ * @param string $contentType Content type
676
+ * @return boolean
677
+ */
678
+ public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null)
679
+ {
680
+ return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
681
+ }
682
+
683
+
684
+ /**
685
+ * Put an object from a string (legacy function)
686
+ *
687
+ * @param string $string Input data
688
+ * @param string $bucket Bucket name
689
+ * @param string $uri Object URI
690
+ * @param constant $acl ACL constant
691
+ * @param array $metaHeaders Array of x-amz-meta-* headers
692
+ * @param string $contentType Content type
693
+ * @return boolean
694
+ */
695
+ public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain')
696
+ {
697
+ return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
698
+ }
699
+
700
+
701
+ /**
702
+ * Get an object
703
+ *
704
+ * @param string $bucket Bucket name
705
+ * @param string $uri Object URI
706
+ * @param mixed $saveTo Filename or resource to write to
707
+ * @return mixed
708
+ */
709
+ public static function getObject($bucket, $uri, $saveTo = false)
710
+ {
711
+ $rest = new mwpS3Request('GET', $bucket, $uri, self::$endpoint);
712
+ if ($saveTo !== false)
713
+ {
714
+ if (is_resource($saveTo))
715
+ $rest->fp =& $saveTo;
716
+ else
717
+ if (($rest->fp = @fopen($saveTo, 'wb')) !== false)
718
+ $rest->file = realpath($saveTo);
719
+ else
720
+ $rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
721
+ }
722
+ if ($rest->response->error === false) $rest->getResponse();
723
+
724
+ if ($rest->response->error === false && $rest->response->code !== 200)
725
+ $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
726
+ if ($rest->response->error !== false)
727
+ {
728
+ self::__triggerError(sprintf("mwpS3::getObject({$bucket}, {$uri}): [%s] %s",
729
+ $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
730
+ return false;
731
+ }
732
+ return $rest->response;
733
+ }
734
+
735
+
736
+ /**
737
+ * Get object information
738
+ *
739
+ * @param string $bucket Bucket name
740
+ * @param string $uri Object URI
741
+ * @param boolean $returnInfo Return response information
742
+ * @return mixed | false
743
+ */
744
+ public static function getObjectInfo($bucket, $uri, $returnInfo = true)
745
+ {
746
+ $rest = new mwpS3Request('HEAD', $bucket, $uri, self::$endpoint);
747
+ $rest = $rest->getResponse();
748
+ if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
749
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
750
+ if ($rest->error !== false)
751
+ {
752
+ self::__triggerError(sprintf("mwpS3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
753
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
754
+ return false;
755
+ }
756
+ return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
757
+ }
758
+
759
+
760
+ /**
761
+ * Copy an object
762
+ *
763
+ * @param string $srcBucket Source bucket name
764
+ * @param string $srcUri Source object URI
765
+ * @param string $bucket Destination bucket name
766
+ * @param string $uri Destination object URI
767
+ * @param constant $acl ACL constant
768
+ * @param array $metaHeaders Optional array of x-amz-meta-* headers
769
+ * @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
770
+ * @param constant $storageClass Storage class constant
771
+ * @return mixed | false
772
+ */
773
+ public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
774
+ {
775
+ $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
776
+ $rest->setHeader('Content-Length', 0);
777
+ foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
778
+ foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
779
+ if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
780
+ $rest->setAmzHeader('x-amz-storage-class', $storageClass);
781
+ $rest->setAmzHeader('x-amz-acl', $acl); // Added rawurlencode() for $srcUri (thanks a.yamanoi)
782
+ $rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, rawurlencode($srcUri)));
783
+ if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
784
+ $rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
785
+
786
+ $rest = $rest->getResponse();
787
+ if ($rest->error === false && $rest->code !== 200)
788
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
789
+ if ($rest->error !== false)
790
+ {
791
+ self::__triggerError(sprintf("mwpS3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
792
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
793
+ return false;
794
+ }
795
+ return isset($rest->body->LastModified, $rest->body->ETag) ? array(
796
+ 'time' => strtotime((string)$rest->body->LastModified),
797
+ 'hash' => substr((string)$rest->body->ETag, 1, -1)
798
+ ) : false;
799
+ }
800
+
801
+
802
+ /**
803
+ * Set up a bucket redirection
804
+ *
805
+ * @param string $bucket Bucket name
806
+ * @param string $location Target host name
807
+ * @return boolean
808
+ */
809
+ public static function setBucketRedirect($bucket = NULL, $location = NULL)
810
+ {
811
+ $rest = new mwpS3Request('PUT', $bucket, '', self::$endpoint);
812
+
813
+ if( empty($bucket) || empty($location) ) {
814
+ self::__triggerError("mwpS3::setBucketRedirect({$bucket}, {$location}): Empty parameter.", __FILE__, __LINE__);
815
+ return false;
816
+ }
817
+
818
+ $dom = new DOMDocument;
819
+ $websiteConfiguration = $dom->createElement('WebsiteConfiguration');
820
+ $redirectAllRequestsTo = $dom->createElement('RedirectAllRequestsTo');
821
+ $hostName = $dom->createElement('HostName', $location);
822
+ $redirectAllRequestsTo->appendChild($hostName);
823
+ $websiteConfiguration->appendChild($redirectAllRequestsTo);
824
+ $dom->appendChild($websiteConfiguration);
825
+ $rest->setParameter('website', null);
826
+ $rest->data = $dom->saveXML();
827
+ $rest->size = strlen($rest->data);
828
+ $rest->setHeader('Content-Type', 'application/xml');
829
+ $rest = $rest->getResponse();
830
+
831
+ if ($rest->error === false && $rest->code !== 200)
832
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
833
+ if ($rest->error !== false)
834
+ {
835
+ self::__triggerError(sprintf("mwpS3::setBucketRedirect({$bucket}, {$location}): [%s] %s",
836
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
837
+ return false;
838
+ }
839
+ return true;
840
+ }
841
+
842
+
843
+ /**
844
+ * Set logging for a bucket
845
+ *
846
+ * @param string $bucket Bucket name
847
+ * @param string $targetBucket Target bucket (where logs are stored)
848
+ * @param string $targetPrefix Log prefix (e,g; domain.com-)
849
+ * @return boolean
850
+ */
851
+ public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null)
852
+ {
853
+ // The S3 log delivery group has to be added to the target bucket's ACP
854
+ if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false)
855
+ {
856
+ // Only add permissions to the target bucket when they do not exist
857
+ $aclWriteSet = false;
858
+ $aclReadSet = false;
859
+ foreach ($acp['acl'] as $acl)
860
+ if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery')
861
+ {
862
+ if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
863
+ elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
864
+ }
865
+ if (!$aclWriteSet) $acp['acl'][] = array(
866
+ 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
867
+ );
868
+ if (!$aclReadSet) $acp['acl'][] = array(
869
+ 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
870
+ );
871
+ if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
872
+ }
873
+
874
+ $dom = new DOMDocument;
875
+ $bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
876
+ $bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
877
+ if ($targetBucket !== null)
878
+ {
879
+ if ($targetPrefix == null) $targetPrefix = $bucket . '-';
880
+ $loggingEnabled = $dom->createElement('LoggingEnabled');
881
+ $loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
882
+ $loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
883
+ // TODO: Add TargetGrants?
884
+ $bucketLoggingStatus->appendChild($loggingEnabled);
885
+ }
886
+ $dom->appendChild($bucketLoggingStatus);
887
+
888
+ $rest = new mwpS3Request('PUT', $bucket, '', self::$endpoint);
889
+ $rest->setParameter('logging', null);
890
+ $rest->data = $dom->saveXML();
891
+ $rest->size = strlen($rest->data);
892
+ $rest->setHeader('Content-Type', 'application/xml');
893
+ $rest = $rest->getResponse();
894
+ if ($rest->error === false && $rest->code !== 200)
895
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
896
+ if ($rest->error !== false)
897
+ {
898
+ self::__triggerError(sprintf("mwpS3::setBucketLogging({$bucket}, {$targetBucket}): [%s] %s",
899
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
900
+ return false;
901
+ }
902
+ return true;
903
+ }
904
+
905
+
906
+ /**
907
+ * Get logging status for a bucket
908
+ *
909
+ * This will return false if logging is not enabled.
910
+ * Note: To enable logging, you also need to grant write access to the log group
911
+ *
912
+ * @param string $bucket Bucket name
913
+ * @return array | false
914
+ */
915
+ public static function getBucketLogging($bucket)
916
+ {
917
+ $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
918
+ $rest->setParameter('logging', null);
919
+ $rest = $rest->getResponse();
920
+ if ($rest->error === false && $rest->code !== 200)
921
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
922
+ if ($rest->error !== false)
923
+ {
924
+ self::__triggerError(sprintf("mwpS3::getBucketLogging({$bucket}): [%s] %s",
925
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
926
+ return false;
927
+ }
928
+ if (!isset($rest->body->LoggingEnabled)) return false; // No logging
929
+ return array(
930
+ 'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
931
+ 'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
932
+ );
933
+ }
934
+
935
+
936
+ /**
937
+ * Disable bucket logging
938
+ *
939
+ * @param string $bucket Bucket name
940
+ * @return boolean
941
+ */
942
+ public static function disableBucketLogging($bucket)
943
+ {
944
+ return self::setBucketLogging($bucket, null);
945
+ }
946
+
947
+
948
+ /**
949
+ * Get a bucket's location
950
+ *
951
+ * @param string $bucket Bucket name
952
+ * @return string | false
953
+ */
954
+ public static function getBucketLocation($bucket)
955
+ {
956
+ $rest = new mwpS3Request('GET', $bucket, '', self::$endpoint);
957
+ $rest->setParameter('location', null);
958
+ $rest = $rest->getResponse();
959
+ if ($rest->error === false && $rest->code !== 200)
960
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
961
+ if ($rest->error !== false)
962
+ {
963
+ self::__triggerError(sprintf("mwpS3::getBucketLocation({$bucket}): [%s] %s",
964
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
965
+ return false;
966
+ }
967
+ return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
968
+ }
969
+
970
+
971
+ /**
972
+ * Set object or bucket Access Control Policy
973
+ *
974
+ * @param string $bucket Bucket name
975
+ * @param string $uri Object URI
976
+ * @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
977
+ * @return boolean
978
+ */
979
+ public static function setAccessControlPolicy($bucket, $uri = '', $acp = array())
980
+ {
981
+ $dom = new DOMDocument;
982
+ $dom->formatOutput = true;
983
+ $accessControlPolicy = $dom->createElement('AccessControlPolicy');
984
+ $accessControlList = $dom->createElement('AccessControlList');
985
+
986
+ // It seems the owner has to be passed along too
987
+ $owner = $dom->createElement('Owner');
988
+ $owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
989
+ $owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
990
+ $accessControlPolicy->appendChild($owner);
991
+
992
+ foreach ($acp['acl'] as $g)
993
+ {
994
+ $grant = $dom->createElement('Grant');
995
+ $grantee = $dom->createElement('Grantee');
996
+ $grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
997
+ if (isset($g['id']))
998
+ { // CanonicalUser (DisplayName is omitted)
999
+ $grantee->setAttribute('xsi:type', 'CanonicalUser');
1000
+ $grantee->appendChild($dom->createElement('ID', $g['id']));
1001
+ }
1002
+ elseif (isset($g['email']))
1003
+ { // AmazonCustomerByEmail
1004
+ $grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
1005
+ $grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
1006
+ }
1007
+ elseif ($g['type'] == 'Group')
1008
+ { // Group
1009
+ $grantee->setAttribute('xsi:type', 'Group');
1010
+ $grantee->appendChild($dom->createElement('URI', $g['uri']));
1011
+ }
1012
+ $grant->appendChild($grantee);
1013
+ $grant->appendChild($dom->createElement('Permission', $g['permission']));
1014
+ $accessControlList->appendChild($grant);
1015
+ }
1016
+
1017
+ $accessControlPolicy->appendChild($accessControlList);
1018
+ $dom->appendChild($accessControlPolicy);
1019
+
1020
+ $rest = new mwpS3Request('PUT', $bucket, $uri, self::$endpoint);
1021
+ $rest->setParameter('acl', null);
1022
+ $rest->data = $dom->saveXML();
1023
+ $rest->size = strlen($rest->data);
1024
+ $rest->setHeader('Content-Type', 'application/xml');
1025
+ $rest = $rest->getResponse();
1026
+ if ($rest->error === false && $rest->code !== 200)
1027
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1028
+ if ($rest->error !== false)
1029
+ {
1030
+ self::__triggerError(sprintf("mwpS3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
1031
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1032
+ return false;
1033
+ }
1034
+ return true;
1035
+ }
1036
+
1037
+
1038
+ /**
1039
+ * Get object or bucket Access Control Policy
1040
+ *
1041
+ * @param string $bucket Bucket name
1042
+ * @param string $uri Object URI
1043
+ * @return mixed | false
1044
+ */
1045
+ public static function getAccessControlPolicy($bucket, $uri = '')
1046
+ {
1047
+ $rest = new mwpS3Request('GET', $bucket, $uri, self::$endpoint);
1048
+ $rest->setParameter('acl', null);
1049
+ $rest = $rest->getResponse();
1050
+ if ($rest->error === false && $rest->code !== 200)
1051
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1052
+ if ($rest->error !== false)
1053
+ {
1054
+ self::__triggerError(sprintf("mwpS3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
1055
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1056
+ return false;
1057
+ }
1058
+
1059
+ $acp = array();
1060
+ if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
1061
+ $acp['owner'] = array(
1062
+ 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
1063
+ );
1064
+
1065
+ if (isset($rest->body->AccessControlList))
1066
+ {
1067
+ $acp['acl'] = array();
1068
+ foreach ($rest->body->AccessControlList->Grant as $grant)
1069
+ {
1070
+ foreach ($grant->Grantee as $grantee)
1071
+ {
1072
+ if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
1073
+ $acp['acl'][] = array(
1074
+ 'type' => 'CanonicalUser',
1075
+ 'id' => (string)$grantee->ID,
1076
+ 'name' => (string)$grantee->DisplayName,
1077
+ 'permission' => (string)$grant->Permission
1078
+ );
1079
+ elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
1080
+ $acp['acl'][] = array(
1081
+ 'type' => 'AmazonCustomerByEmail',
1082
+ 'email' => (string)$grantee->EmailAddress,
1083
+ 'permission' => (string)$grant->Permission
1084
+ );
1085
+ elseif (isset($grantee->URI)) // Group
1086
+ $acp['acl'][] = array(
1087
+ 'type' => 'Group',
1088
+ 'uri' => (string)$grantee->URI,
1089
+ 'permission' => (string)$grant->Permission
1090
+ );
1091
+ else continue;
1092
+ }
1093
+ }
1094
+ }
1095
+ return $acp;
1096
+ }
1097
+
1098
+
1099
+ /**
1100
+ * Delete an object
1101
+ *
1102
+ * @param string $bucket Bucket name
1103
+ * @param string $uri Object URI
1104
+ * @return boolean
1105
+ */
1106
+ public static function deleteObject($bucket, $uri)
1107
+ {
1108
+ $rest = new mwpS3Request('DELETE', $bucket, $uri, self::$endpoint);
1109
+ $rest = $rest->getResponse();
1110
+ if ($rest->error === false && $rest->code !== 204)
1111
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1112
+ if ($rest->error !== false)
1113
+ {
1114
+ self::__triggerError(sprintf("mwpS3::deleteObject(): [%s] %s",
1115
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1116
+ return false;
1117
+ }
1118
+ return true;
1119
+ }
1120
+
1121
+
1122
+ /**
1123
+ * Get a query string authenticated URL
1124
+ *
1125
+ * @param string $bucket Bucket name
1126
+ * @param string $uri Object URI
1127
+ * @param integer $lifetime Lifetime in seconds
1128
+ * @param boolean $hostBucket Use the bucket name as the hostname
1129
+ * @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
1130
+ * @return string
1131
+ */
1132
+ public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false)
1133
+ {
1134
+ $expires = time() + $lifetime;
1135
+ $uri = str_replace(array('%2F', '%2B'), array('/', '+'), rawurlencode($uri));
1136
+ return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
1137
+ // $hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
1138
+ $hostBucket ? $bucket : self::$endpoint.'/'.$bucket, $uri, self::$__accessKey, $expires,
1139
+ urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
1140
+ }
1141
+
1142
+
1143
+ /**
1144
+ * Get a CloudFront signed policy URL
1145
+ *
1146
+ * @param array $policy Policy
1147
+ * @return string
1148
+ */
1149
+ public static function getSignedPolicyURL($policy)
1150
+ {
1151
+ $data = json_encode($policy);
1152
+ $signature = '';
1153
+ if (!openssl_sign($data, $signature, self::$__signingKeyResource)) return false;
1154
+
1155
+ $encoded = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($data));
1156
+ $signature = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($signature));
1157
+
1158
+ $url = $policy['Statement'][0]['Resource'] . '?';
1159
+ foreach (array('Policy' => $encoded, 'Signature' => $signature, 'Key-Pair-Id' => self::$__signingKeyPairId) as $k => $v)
1160
+ $url .= $k.'='.str_replace('%2F', '/', rawurlencode($v)).'&';
1161
+ return substr($url, 0, -1);
1162
+ }
1163
+
1164
+
1165
+ /**
1166
+ * Get a CloudFront canned policy URL
1167
+ *
1168
+ * @param string $url URL to sign
1169
+ * @param integer $lifetime URL lifetime
1170
+ * @return string
1171
+ */
1172
+ public static function getSignedCannedURL($url, $lifetime)
1173
+ {
1174
+ return self::getSignedPolicyURL(array(
1175
+ 'Statement' => array(
1176
+ array('Resource' => $url, 'Condition' => array(
1177
+ 'DateLessThan' => array('AWS:EpochTime' => time() + $lifetime)
1178
+ ))
1179
+ )
1180
+ ));
1181
+ }
1182
+
1183
+
1184
+ /**
1185
+ * Get upload POST parameters for form uploads
1186
+ *
1187
+ * @param string $bucket Bucket name
1188
+ * @param string $uriPrefix Object URI prefix
1189
+ * @param constant $acl ACL constant
1190
+ * @param integer $lifetime Lifetime in seconds
1191
+ * @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
1192
+ * @param string $successRedirect Redirect URL or 200 / 201 status code
1193
+ * @param array $amzHeaders Array of x-amz-meta-* headers
1194
+ * @param array $headers Array of request headers or content type as a string
1195
+ * @param boolean $flashVars Includes additional "Filename" variable posted by Flash
1196
+ * @return object
1197
+ */
1198
+ public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600,
1199
+ $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false)
1200
+ {
1201
+ // Create policy object
1202
+ $policy = new stdClass;
1203
+ $policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
1204
+ $policy->conditions = array();
1205
+ $obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
1206
+ $obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
1207
+
1208
+ $obj = new stdClass; // 200 for non-redirect uploads
1209
+ if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1210
+ $obj->success_action_status = (string)$successRedirect;
1211
+ else // URL
1212
+ $obj->success_action_redirect = $successRedirect;
1213
+ array_push($policy->conditions, $obj);
1214
+
1215
+ if ($acl !== self::ACL_PUBLIC_READ)
1216
+ array_push($policy->conditions, array('eq', '$acl', $acl));
1217
+
1218
+ array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
1219
+ if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
1220
+ foreach (array_keys($headers) as $headerKey)
1221
+ array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
1222
+ foreach ($amzHeaders as $headerKey => $headerVal)
1223
+ {
1224
+ $obj = new stdClass;
1225
+ $obj->{$headerKey} = (string)$headerVal;
1226
+ array_push($policy->conditions, $obj);
1227
+ }
1228
+ array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
1229
+ $policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
1230
+
1231
+ // Create parameters
1232
+ $params = new stdClass;
1233
+ $params->AWSAccessKeyId = self::$__accessKey;
1234
+ $params->key = $uriPrefix.'${filename}';
1235
+ $params->acl = $acl;
1236
+ $params->policy = $policy; unset($policy);
1237
+ $params->signature = self::__getHash($params->policy);
1238
+ if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1239
+ $params->success_action_status = (string)$successRedirect;
1240
+ else
1241
+ $params->success_action_redirect = $successRedirect;
1242
+ foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1243
+ foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1244
+ return $params;
1245
+ }
1246
+
1247
+
1248
+ /**
1249
+ * Create a CloudFront distribution
1250
+ *
1251
+ * @param string $bucket Bucket name
1252
+ * @param boolean $enabled Enabled (true/false)
1253
+ * @param array $cnames Array containing CNAME aliases
1254
+ * @param string $comment Use the bucket name as the hostname
1255
+ * @param string $defaultRootObject Default root object
1256
+ * @param string $originAccessIdentity Origin access identity
1257
+ * @param array $trustedSigners Array of trusted signers
1258
+ * @return array | false
1259
+ */
1260
+ public static function createDistribution($bucket, $enabled = true, $cnames = array(), $comment = null, $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1261
+ {
1262
+ if (!extension_loaded('openssl'))
1263
+ {
1264
+ self::__triggerError(sprintf("mwpS3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): %s",
1265
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1266
+ return false;
1267
+ }
1268
+ $useSSL = self::$useSSL;
1269
+
1270
+ self::$useSSL = true; // CloudFront requires SSL
1271
+ $rest = new mwpS3Request('POST', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1272
+ $rest->data = self::__getCloudFrontDistributionConfigXML(
1273
+ $bucket.'.s3.amazonaws.com',
1274
+ $enabled,
1275
+ (string)$comment,
1276
+ (string)microtime(true),
1277
+ $cnames,
1278
+ $defaultRootObject,
1279
+ $originAccessIdentity,
1280
+ $trustedSigners
1281
+ );
1282
+
1283
+ $rest->size = strlen($rest->data);
1284
+ $rest->setHeader('Content-Type', 'application/xml');
1285
+ $rest = self::__getCloudFrontResponse($rest);
1286
+
1287
+ self::$useSSL = $useSSL;
1288
+
1289
+ if ($rest->error === false && $rest->code !== 201)
1290
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1291
+ if ($rest->error !== false)
1292
+ {
1293
+ self::__triggerError(sprintf("mwpS3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): [%s] %s",
1294
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1295
+ return false;
1296
+ } elseif ($rest->body instanceof SimpleXMLElement)
1297
+ return self::__parseCloudFrontDistributionConfig($rest->body);
1298
+ return false;
1299
+ }
1300
+
1301
+
1302
+ /**
1303
+ * Get CloudFront distribution info
1304
+ *
1305
+ * @param string $distributionId Distribution ID from listDistributions()
1306
+ * @return array | false
1307
+ */
1308
+ public static function getDistribution($distributionId)
1309
+ {
1310
+ if (!extension_loaded('openssl'))
1311
+ {
1312
+ self::__triggerError(sprintf("mwpS3::getDistribution($distributionId): %s",
1313
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1314
+ return false;
1315
+ }
1316
+ $useSSL = self::$useSSL;
1317
+
1318
+ self::$useSSL = true; // CloudFront requires SSL
1319
+ $rest = new mwpS3Request('GET', '', '2010-11-01/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
1320
+ $rest = self::__getCloudFrontResponse($rest);
1321
+
1322
+ self::$useSSL = $useSSL;
1323
+
1324
+ if ($rest->error === false && $rest->code !== 200)
1325
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1326
+ if ($rest->error !== false)
1327
+ {
1328
+ self::__triggerError(sprintf("mwpS3::getDistribution($distributionId): [%s] %s",
1329
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1330
+ return false;
1331
+ }
1332
+ elseif ($rest->body instanceof SimpleXMLElement)
1333
+ {
1334
+ $dist = self::__parseCloudFrontDistributionConfig($rest->body);
1335
+ $dist['hash'] = $rest->headers['hash'];
1336
+ $dist['id'] = $distributionId;
1337
+ return $dist;
1338
+ }
1339
+ return false;
1340
+ }
1341
+
1342
+
1343
+ /**
1344
+ * Update a CloudFront distribution
1345
+ *
1346
+ * @param array $dist Distribution array info identical to output of getDistribution()
1347
+ * @return array | false
1348
+ */
1349
+ public static function updateDistribution($dist)
1350
+ {
1351
+ if (!extension_loaded('openssl'))
1352
+ {
1353
+ self::__triggerError(sprintf("mwpS3::updateDistribution({$dist['id']}): %s",
1354
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1355
+ return false;
1356
+ }
1357
+
1358
+ $useSSL = self::$useSSL;
1359
+
1360
+ self::$useSSL = true; // CloudFront requires SSL
1361
+ $rest = new mwpS3Request('PUT', '', '2010-11-01/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
1362
+ $rest->data = self::__getCloudFrontDistributionConfigXML(
1363
+ $dist['origin'],
1364
+ $dist['enabled'],
1365
+ $dist['comment'],
1366
+ $dist['callerReference'],
1367
+ $dist['cnames'],
1368
+ $dist['defaultRootObject'],
1369
+ $dist['originAccessIdentity'],
1370
+ $dist['trustedSigners']
1371
+ );
1372
+
1373
+ $rest->size = strlen($rest->data);
1374
+ $rest->setHeader('If-Match', $dist['hash']);
1375
+ $rest = self::__getCloudFrontResponse($rest);
1376
+
1377
+ self::$useSSL = $useSSL;
1378
+
1379
+ if ($rest->error === false && $rest->code !== 200)
1380
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1381
+ if ($rest->error !== false)
1382
+ {
1383
+ self::__triggerError(sprintf("mwpS3::updateDistribution({$dist['id']}): [%s] %s",
1384
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1385
+ return false;
1386
+ } else {
1387
+ $dist = self::__parseCloudFrontDistributionConfig($rest->body);
1388
+ $dist['hash'] = $rest->headers['hash'];
1389
+ return $dist;
1390
+ }
1391
+ return false;
1392
+ }
1393
+
1394
+
1395
+ /**
1396
+ * Delete a CloudFront distribution
1397
+ *
1398
+ * @param array $dist Distribution array info identical to output of getDistribution()
1399
+ * @return boolean
1400
+ */
1401
+ public static function deleteDistribution($dist)
1402
+ {
1403
+ if (!extension_loaded('openssl'))
1404
+ {
1405
+ self::__triggerError(sprintf("mwpS3::deleteDistribution({$dist['id']}): %s",
1406
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1407
+ return false;
1408
+ }
1409
+
1410
+ $useSSL = self::$useSSL;
1411
+
1412
+ self::$useSSL = true; // CloudFront requires SSL
1413
+ $rest = new mwpS3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
1414
+ $rest->setHeader('If-Match', $dist['hash']);
1415
+ $rest = self::__getCloudFrontResponse($rest);
1416
+
1417
+ self::$useSSL = $useSSL;
1418
+
1419
+ if ($rest->error === false && $rest->code !== 204)
1420
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1421
+ if ($rest->error !== false)
1422
+ {
1423
+ self::__triggerError(sprintf("mwpS3::deleteDistribution({$dist['id']}): [%s] %s",
1424
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1425
+ return false;
1426
+ }
1427
+ return true;
1428
+ }
1429
+
1430
+
1431
+ /**
1432
+ * Get a list of CloudFront distributions
1433
+ *
1434
+ * @return array
1435
+ */
1436
+ public static function listDistributions()
1437
+ {
1438
+ if (!extension_loaded('openssl'))
1439
+ {
1440
+ self::__triggerError(sprintf("mwpS3::listDistributions(): [%s] %s",
1441
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1442
+ return false;
1443
+ }
1444
+
1445
+ $useSSL = self::$useSSL;
1446
+ self::$useSSL = true; // CloudFront requires SSL
1447
+ $rest = new mwpS3Request('GET', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1448
+ $rest = self::__getCloudFrontResponse($rest);
1449
+ self::$useSSL = $useSSL;
1450
+
1451
+ if ($rest->error === false && $rest->code !== 200)
1452
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1453
+ if ($rest->error !== false)
1454
+ {
1455
+ self::__triggerError(sprintf("mwpS3::listDistributions(): [%s] %s",
1456
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1457
+ return false;
1458
+ }
1459
+ elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary))
1460
+ {
1461
+ $list = array();
1462
+ if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated))
1463
+ {
1464
+ //$info['marker'] = (string)$rest->body->Marker;
1465
+ //$info['maxItems'] = (int)$rest->body->MaxItems;
1466
+ //$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
1467
+ }
1468
+ foreach ($rest->body->DistributionSummary as $summary)
1469
+ $list[(string)$summary->Id] = self::__parseCloudFrontDistributionConfig($summary);
1470
+
1471
+ return $list;
1472
+ }
1473
+ return array();
1474
+ }
1475
+
1476
+ /**
1477
+ * List CloudFront Origin Access Identities
1478
+ *
1479
+ * @return array
1480
+ */
1481
+ public static function listOriginAccessIdentities()
1482
+ {
1483
+ if (!extension_loaded('openssl'))
1484
+ {
1485
+ self::__triggerError(sprintf("mwpS3::listOriginAccessIdentities(): [%s] %s",
1486
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1487
+ return false;
1488
+ }
1489
+
1490
+ self::$useSSL = true; // CloudFront requires SSL
1491
+ $rest = new mwpS3Request('GET', '', '2010-11-01/origin-access-identity/cloudfront', 'cloudfront.amazonaws.com');
1492
+ $rest = self::__getCloudFrontResponse($rest);
1493
+ $useSSL = self::$useSSL;
1494
+
1495
+ if ($rest->error === false && $rest->code !== 200)
1496
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1497
+ if ($rest->error !== false)
1498
+ {
1499
+ trigger_error(sprintf("mwpS3::listOriginAccessIdentities(): [%s] %s",
1500
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
1501
+ return false;
1502
+ }
1503
+
1504
+ if (isset($rest->body->CloudFrontOriginAccessIdentitySummary))
1505
+ {
1506
+ $identities = array();
1507
+ foreach ($rest->body->CloudFrontOriginAccessIdentitySummary as $identity)
1508
+ if (isset($identity->S3CanonicalUserId))
1509
+ $identities[(string)$identity->Id] = array('id' => (string)$identity->Id, 's3CanonicalUserId' => (string)$identity->S3CanonicalUserId);
1510
+ return $identities;
1511
+ }
1512
+ return false;
1513
+ }
1514
+
1515
+
1516
+ /**
1517
+ * Invalidate objects in a CloudFront distribution
1518
+ *
1519
+ * Thanks to Martin Lindkvist for mwpS3::invalidateDistribution()
1520
+ *
1521
+ * @param string $distributionId Distribution ID from listDistributions()
1522
+ * @param array $paths Array of object paths to invalidate
1523
+ * @return boolean
1524
+ */
1525
+ public static function invalidateDistribution($distributionId, $paths)
1526
+ {
1527
+ if (!extension_loaded('openssl'))
1528
+ {
1529
+ self::__triggerError(sprintf("mwpS3::invalidateDistribution(): [%s] %s",
1530
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1531
+ return false;
1532
+ }
1533
+
1534
+ $useSSL = self::$useSSL;
1535
+ self::$useSSL = true; // CloudFront requires SSL
1536
+ $rest = new mwpS3Request('POST', '', '2010-08-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
1537
+ $rest->data = self::__getCloudFrontInvalidationBatchXML($paths, (string)microtime(true));
1538
+ $rest->size = strlen($rest->data);
1539
+ $rest = self::__getCloudFrontResponse($rest);
1540
+ self::$useSSL = $useSSL;
1541
+
1542
+ if ($rest->error === false && $rest->code !== 201)
1543
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1544
+ if ($rest->error !== false)
1545
+ {
1546
+ trigger_error(sprintf("mwpS3::invalidate('{$distributionId}',{$paths}): [%s] %s",
1547
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
1548
+ return false;
1549
+ }
1550
+ return true;
1551
+ }
1552
+
1553
+
1554
+ /**
1555
+ * Get a InvalidationBatch DOMDocument
1556
+ *
1557
+ * @internal Used to create XML in invalidateDistribution()
1558
+ * @param array $paths Paths to objects to invalidateDistribution
1559
+ * @param int $callerReference
1560
+ * @return string
1561
+ */
1562
+ private static function __getCloudFrontInvalidationBatchXML($paths, $callerReference = '0')
1563
+ {
1564
+ $dom = new DOMDocument('1.0', 'UTF-8');
1565
+ $dom->formatOutput = true;
1566
+ $invalidationBatch = $dom->createElement('InvalidationBatch');
1567
+ foreach ($paths as $path)
1568
+ $invalidationBatch->appendChild($dom->createElement('Path', $path));
1569
+
1570
+ $invalidationBatch->appendChild($dom->createElement('CallerReference', $callerReference));
1571
+ $dom->appendChild($invalidationBatch);
1572
+ return $dom->saveXML();
1573
+ }
1574
+
1575
+
1576
+ /**
1577
+ * List your invalidation batches for invalidateDistribution() in a CloudFront distribution
1578
+ *
1579
+ * http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListInvalidation.html
1580
+ * returned array looks like this:
1581
+ * Array
1582
+ * (
1583
+ * [I31TWB0CN9V6XD] => InProgress
1584
+ * [IT3TFE31M0IHZ] => Completed
1585
+ * [I12HK7MPO1UQDA] => Completed
1586
+ * [I1IA7R6JKTC3L2] => Completed
1587
+ * )
1588
+ *
1589
+ * @param string $distributionId Distribution ID from listDistributions()
1590
+ * @return array
1591
+ */
1592
+ public static function getDistributionInvalidationList($distributionId)
1593
+ {
1594
+ if (!extension_loaded('openssl'))
1595
+ {
1596
+ self::__triggerError(sprintf("S3::getDistributionInvalidationList(): [%s] %s",
1597
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1598
+ return false;
1599
+ }
1600
+
1601
+ $useSSL = self::$useSSL;
1602
+ self::$useSSL = true; // CloudFront requires SSL
1603
+ $rest = new mwpS3Request('GET', '', '2010-11-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
1604
+ $rest = self::__getCloudFrontResponse($rest);
1605
+ self::$useSSL = $useSSL;
1606
+
1607
+ if ($rest->error === false && $rest->code !== 200)
1608
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1609
+ if ($rest->error !== false)
1610
+ {
1611
+ trigger_error(sprintf("mwpS3::getDistributionInvalidationList('{$distributionId}'): [%s]",
1612
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
1613
+ return false;
1614
+ }
1615
+ elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->InvalidationSummary))
1616
+ {
1617
+ $list = array();
1618
+ foreach ($rest->body->InvalidationSummary as $summary)
1619
+ $list[(string)$summary->Id] = (string)$summary->Status;
1620
+
1621
+ return $list;
1622
+ }
1623
+ return array();
1624
+ }
1625
+
1626
+
1627
+ /**
1628
+ * Get a DistributionConfig DOMDocument
1629
+ *
1630
+ * http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?PutConfig.html
1631
+ *
1632
+ * @internal Used to create XML in createDistribution() and updateDistribution()
1633
+ * @param string $bucket S3 Origin bucket
1634
+ * @param boolean $enabled Enabled (true/false)
1635
+ * @param string $comment Comment to append
1636
+ * @param string $callerReference Caller reference
1637
+ * @param array $cnames Array of CNAME aliases
1638
+ * @param string $defaultRootObject Default root object
1639
+ * @param string $originAccessIdentity Origin access identity
1640
+ * @param array $trustedSigners Array of trusted signers
1641
+ * @return string
1642
+ */
1643
+ private static function __getCloudFrontDistributionConfigXML($bucket, $enabled, $comment, $callerReference = '0', $cnames = array(), $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1644
+ {
1645
+ $dom = new DOMDocument('1.0', 'UTF-8');
1646
+ $dom->formatOutput = true;
1647
+ $distributionConfig = $dom->createElement('DistributionConfig');
1648
+ $distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2010-11-01/');
1649
+
1650
+ $origin = $dom->createElement('S3Origin');
1651
+ $origin->appendChild($dom->createElement('DNSName', $bucket));
1652
+ if ($originAccessIdentity !== null) $origin->appendChild($dom->createElement('OriginAccessIdentity', $originAccessIdentity));
1653
+ $distributionConfig->appendChild($origin);
1654
+
1655
+ if ($defaultRootObject !== null) $distributionConfig->appendChild($dom->createElement('DefaultRootObject', $defaultRootObject));
1656
+
1657
+ $distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
1658
+ foreach ($cnames as $cname)
1659
+ $distributionConfig->appendChild($dom->createElement('CNAME', $cname));
1660
+ if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
1661
+ $distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
1662
+
1663
+ $trusted = $dom->createElement('TrustedSigners');
1664
+ foreach ($trustedSigners as $id => $type)
1665
+ $trusted->appendChild($id !== '' ? $dom->createElement($type, $id) : $dom->createElement($type));
1666
+ $distributionConfig->appendChild($trusted);
1667
+
1668
+ $dom->appendChild($distributionConfig);
1669
+ //var_dump($dom->saveXML());
1670
+ return $dom->saveXML();
1671
+ }
1672
+
1673
+
1674
+ /**
1675
+ * Parse a CloudFront distribution config
1676
+ *
1677
+ * See http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?GetDistribution.html
1678
+ *
1679
+ * @internal Used to parse the CloudFront DistributionConfig node to an array
1680
+ * @param object &$node DOMNode
1681
+ * @return array
1682
+ */
1683
+ private static function __parseCloudFrontDistributionConfig(&$node)
1684
+ {
1685
+ if (isset($node->DistributionConfig))
1686
+ return self::__parseCloudFrontDistributionConfig($node->DistributionConfig);
1687
+
1688
+ $dist = array();
1689
+ if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName))
1690
+ {
1691
+ $dist['id'] = (string)$node->Id;
1692
+ $dist['status'] = (string)$node->Status;
1693
+ $dist['time'] = strtotime((string)$node->LastModifiedTime);
1694
+ $dist['domain'] = (string)$node->DomainName;
1695
+ }
1696
+
1697
+ if (isset($node->CallerReference))
1698
+ $dist['callerReference'] = (string)$node->CallerReference;
1699
+
1700
+ if (isset($node->Enabled))
1701
+ $dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
1702
+
1703
+ if (isset($node->S3Origin))
1704
+ {
1705
+ if (isset($node->S3Origin->DNSName))
1706
+ $dist['origin'] = (string)$node->S3Origin->DNSName;
1707
+
1708
+ $dist['originAccessIdentity'] = isset($node->S3Origin->OriginAccessIdentity) ?
1709
+ (string)$node->S3Origin->OriginAccessIdentity : null;
1710
+ }
1711
+
1712
+ $dist['defaultRootObject'] = isset($node->DefaultRootObject) ? (string)$node->DefaultRootObject : null;
1713
+
1714
+ $dist['cnames'] = array();
1715
+ if (isset($node->CNAME))
1716
+ foreach ($node->CNAME as $cname)
1717
+ $dist['cnames'][(string)$cname] = (string)$cname;
1718
+
1719
+ $dist['trustedSigners'] = array();
1720
+ if (isset($node->TrustedSigners))
1721
+ foreach ($node->TrustedSigners as $signer)
1722
+ {
1723
+ if (isset($signer->Self))
1724
+ $dist['trustedSigners'][''] = 'Self';
1725
+ elseif (isset($signer->KeyPairId))
1726
+ $dist['trustedSigners'][(string)$signer->KeyPairId] = 'KeyPairId';
1727
+ elseif (isset($signer->AwsAccountNumber))
1728
+ $dist['trustedSigners'][(string)$signer->AwsAccountNumber] = 'AwsAccountNumber';
1729
+ }
1730
+
1731
+ $dist['comment'] = isset($node->Comment) ? (string)$node->Comment : null;
1732
+ return $dist;
1733
+ }
1734
+
1735
+
1736
+ /**
1737
+ * Grab CloudFront response
1738
+ *
1739
+ * @internal Used to parse the CloudFront S3Request::getResponse() output
1740
+ * @param object &$rest S3Request instance
1741
+ * @return object
1742
+ */
1743
+ private static function __getCloudFrontResponse(&$rest)
1744
+ {
1745
+ $rest->getResponse();
1746
+ if ($rest->response->error === false && isset($rest->response->body) &&
1747
+ is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml')
1748
+ {
1749
+ $rest->response->body = simplexml_load_string($rest->response->body);
1750
+ // Grab CloudFront errors
1751
+ if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
1752
+ $rest->response->body->Error->Message))
1753
+ {
1754
+ $rest->response->error = array(
1755
+ 'code' => (string)$rest->response->body->Error->Code,
1756
+ 'message' => (string)$rest->response->body->Error->Message
1757
+ );
1758
+ unset($rest->response->body);
1759
+ }
1760
+ }
1761
+ return $rest->response;
1762
+ }
1763
+
1764
+
1765
+ /**
1766
+ * Get MIME type for file
1767
+ *
1768
+ * To override the putObject() Content-Type, add it to $requestHeaders
1769
+ *
1770
+ * To use fileinfo, ensure the MAGIC environment variable is set
1771
+ *
1772
+ * @internal Used to get mime types
1773
+ * @param string &$file File path
1774
+ * @return string
1775
+ */
1776
+ private static function __getMIMEType(&$file)
1777
+ {
1778
+ static $exts = array(
1779
+ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif',
1780
+ 'png' => 'image/png', 'ico' => 'image/x-icon', 'pdf' => 'application/pdf',
1781
+ 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'svg' => 'image/svg+xml',
1782
+ 'svgz' => 'image/svg+xml', 'swf' => 'application/x-shockwave-flash',
1783
+ 'zip' => 'application/zip', 'gz' => 'application/x-gzip',
1784
+ 'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
1785
+ 'bz2' => 'application/x-bzip2', 'rar' => 'application/x-rar-compressed',
1786
+ 'exe' => 'application/x-msdownload', 'msi' => 'application/x-msdownload',
1787
+ 'cab' => 'application/vnd.ms-cab-compressed', 'txt' => 'text/plain',
1788
+ 'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
1789
+ 'css' => 'text/css', 'js' => 'text/javascript',
1790
+ 'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
1791
+ 'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
1792
+ 'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
1793
+ 'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
1794
+ );
1795
+
1796
+ $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
1797
+ if (isset($exts[$ext])) return $exts[$ext];
1798
+
1799
+ // Use fileinfo if available
1800
+ if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
1801
+ ($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false)
1802
+ {
1803
+ if (($type = finfo_file($finfo, $file)) !== false)
1804
+ {
1805
+ // Remove the charset and grab the last content-type
1806
+ $type = explode(' ', str_replace('; charset=', ';charset=', $type));
1807
+ $type = array_pop($type);
1808
+ $type = explode(';', $type);
1809
+ $type = trim(array_shift($type));
1810
+ }
1811
+ finfo_close($finfo);
1812
+ if ($type !== false && strlen($type) > 0) return $type;
1813
+ }
1814
+
1815
+ return 'application/octet-stream';
1816
+ }
1817
+
1818
+
1819
+ /**
1820
+ * Generate the auth string: "AWS AccessKey:Signature"
1821
+ *
1822
+ * @internal Used by S3Request::getResponse()
1823
+ * @param string $string String to sign
1824
+ * @return string
1825
+ */
1826
+ public static function __getSignature($string)
1827
+ {
1828
+ return 'AWS '.self::$__accessKey.':'.self::__getHash($string);
1829
+ }
1830
+
1831
+
1832
+ /**
1833
+ * Creates a HMAC-SHA1 hash
1834
+ *
1835
+ * This uses the hash extension if loaded
1836
+ *
1837
+ * @internal Used by __getSignature()
1838
+ * @param string $string String to sign
1839
+ * @return string
1840
+ */
1841
+ private static function __getHash($string)
1842
+ {
1843
+ return base64_encode(extension_loaded('hash') ?
1844
+ hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
1845
+ (str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
1846
+ pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
1847
+ (str_repeat(chr(0x36), 64))) . $string)))));
1848
+ }
1849
 
1850
  }
1851
 
1852
+ /**
1853
+ * mwpS3 Request class
1854
+ *
1855
+ * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
1856
+ * @version 0.5.0-dev
1857
+ */
1858
  final class mwpS3Request
1859
  {
1860
+ /**
1861
+ * AWS URI
1862
+ *
1863
+ * @var string
1864
+ * @access pricate
1865
+ */
1866
+ private $endpoint;
1867
+
1868
+ /**
1869
+ * Verb
1870
+ *
1871
+ * @var string
1872
+ * @access private
1873
+ */
1874
+ private $verb;
1875
+
1876
+ /**
1877
+ * S3 bucket name
1878
+ *
1879
+ * @var string
1880
+ * @access private
1881
+ */
1882
+ private $bucket;
1883
+
1884
+ /**
1885
+ * Object URI
1886
+ *
1887
+ * @var string
1888
+ * @access private
1889
+ */
1890
+ private $uri;
1891
+
1892
+ /**
1893
+ * Final object URI
1894
+ *
1895
+ * @var string
1896
+ * @access private
1897
+ */
1898
+ private $resource = '';
1899
+
1900
+ /**
1901
+ * Additional request parameters
1902
+ *
1903
+ * @var array
1904
+ * @access private
1905
+ */
1906
+ private $parameters = array();
1907
+
1908
+ /**
1909
+ * Amazon specific request headers
1910
+ *
1911
+ * @var array
1912
+ * @access private
1913
+ */
1914
+ private $amzHeaders = array();
1915
+
1916
+ /**
1917
+ * HTTP request headers
1918
+ *
1919
+ * @var array
1920
+ * @access private
1921
+ */
1922
+ private $headers = array(
1923
+ 'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
1924
+ );
1925
+
1926
+ /**
1927
+ * Use HTTP PUT?
1928
+ *
1929
+ * @var bool
1930
+ * @access public
1931
+ */
1932
+ public $fp = false;
1933
+
1934
+ /**
1935
+ * PUT file size
1936
+ *
1937
+ * @var int
1938
+ * @access public
1939
+ */
1940
+ public $size = 0;
1941
+
1942
+ /**
1943
+ * PUT post fields
1944
+ *
1945
+ * @var array
1946
+ * @access public
1947
+ */
1948
+ public $data = false;
1949
+
1950
+ /**
1951
+ * S3 request respone
1952
+ *
1953
+ * @var object
1954
+ * @access public
1955
+ */
1956
+ public $response;
1957
+
1958
+
1959
+ /**
1960
+ * Constructor
1961
+ *
1962
+ * @param string $verb Verb
1963
+ * @param string $bucket Bucket name
1964
+ * @param string $uri Object URI
1965
+ * @param string $endpoint AWS endpoint URI
1966
+ * @return mixed
1967
+ */
1968
+ function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com')
1969
+ {
1970
+
1971
+ $this->endpoint = $endpoint;
1972
+ $this->verb = $verb;
1973
+ $this->bucket = $bucket;
1974
+ $this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
1975
+
1976
+ //if ($this->bucket !== '')
1977
+ // $this->resource = '/'.$this->bucket.$this->uri;
1978
+ //else
1979
+ // $this->resource = $this->uri;
1980
+
1981
+ if ($this->bucket !== '')
1982
+ {
1983
+ if ($this->__dnsBucketName($this->bucket))
1984
+ {
1985
+ $this->headers['Host'] = $this->bucket.'.'.$this->endpoint;
1986
+ $this->resource = '/'.$this->bucket.$this->uri;
1987
+ }
1988
+ else
1989
+ {
1990
+ $this->headers['Host'] = $this->endpoint;
1991
+ $this->uri = $this->uri;
1992
+ if ($this->bucket !== '') $this->uri = '/'.$this->bucket.$this->uri;
1993
+ $this->bucket = '';
1994
+ $this->resource = $this->uri;
1995
+ }
1996
+ }
1997
+ else
1998
+ {
1999
+ $this->headers['Host'] = $this->endpoint;
2000
+ $this->resource = $this->uri;
2001
+ }
2002
+
2003
+
2004
+ $this->headers['Date'] = gmdate('D, d M Y H:i:s T');
2005
+ $this->response = new STDClass;
2006
+ $this->response->error = false;
2007
+ $this->response->body = null;
2008
+ $this->response->headers = array();
2009
+ }
2010
+
2011
+
2012
+ /**
2013
+ * Set request parameter
2014
+ *
2015
+ * @param string $key Key
2016
+ * @param string $value Value
2017
+ * @return void
2018
+ */
2019
+ public function setParameter($key, $value)
2020
+ {
2021
+ $this->parameters[$key] = $value;
2022
+ }
2023
+
2024
+
2025
+ /**
2026
+ * Set request header
2027
+ *
2028
+ * @param string $key Key
2029
+ * @param string $value Value
2030
+ * @return void
2031
+ */
2032
+ public function setHeader($key, $value)
2033
+ {
2034
+ $this->headers[$key] = $value;
2035
+ }
2036
+
2037
+
2038
+ /**
2039
+ * Set x-amz-meta-* header
2040
+ *
2041
+ * @param string $key Key
2042
+ * @param string $value Value
2043
+ * @return void
2044
+ */
2045
+ public function setAmzHeader($key, $value)
2046
+ {
2047
+ $this->amzHeaders[$key] = $value;
2048
+ }
2049
+
2050
+
2051
+ /**
2052
+ * Get the S3 response
2053
+ *
2054
+ * @return object | false
2055
+ */
2056
+ public function getResponse()
2057
+ {
2058
+ $query = '';
2059
+ if (sizeof($this->parameters) > 0)
2060
+ {
2061
+ $query = substr($this->uri, -1) !== '?' ? '?' : '&';
2062
+ foreach ($this->parameters as $var => $value)
2063
+ if ($value == null || $value == '') $query .= $var.'&';
2064
+ // Parameters should be encoded (thanks Sean O'Dea)
2065
+ else $query .= $var.'='.rawurlencode($value).'&';
2066
+ $query = substr($query, 0, -1);
2067
+ $this->uri .= $query;
2068
+
2069
+ if (array_key_exists('acl', $this->parameters) ||
2070
+ array_key_exists('location', $this->parameters) ||
2071
+ array_key_exists('torrent', $this->parameters) ||
2072
+ array_key_exists('website', $this->parameters) ||
2073
+ array_key_exists('logging', $this->parameters))
2074
+ $this->resource .= $query;
2075
+ }
2076
+ $url = (mwpS3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
2077
+
2078
+ //var_dump('bucket: ' . $this->bucket, 'uri: ' . $this->uri, 'resource: ' . $this->resource, 'url: ' . $url);
2079
+
2080
+ // Basic setup
2081
+ $curl = curl_init();
2082
+ curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
2083
+ curl_setopt($curl, CURLOPT_TIMEOUT, 600);
2084
+ if (mwpS3::$useSSL)
2085
+ {
2086
+ // SSL Validation can now be optional for those with broken OpenSSL installations
2087
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, mwpS3::$useSSLValidation ? 2 : 0);
2088
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, mwpS3::$useSSLValidation ? 1 : 0);
2089
+
2090
+ if (mwpS3::$sslKey !== null) curl_setopt($curl, CURLOPT_SSLKEY, mwpS3::$sslKey);
2091
+ if (mwpS3::$sslCert !== null) curl_setopt($curl, CURLOPT_SSLCERT, mwpS3::$sslCert);
2092
+ if (mwpS3::$sslCACert !== null) curl_setopt($curl, CURLOPT_CAINFO, mwpS3::$sslCACert);
2093
+ }
2094
+
2095
+ curl_setopt($curl, CURLOPT_URL, $url);
2096
+
2097
+ if (mwpS3::$proxy != null && isset(mwpS3::$proxy['host']))
2098
+ {
2099
+ curl_setopt($curl, CURLOPT_PROXY, mwpS3::$proxy['host']);
2100
+ curl_setopt($curl, CURLOPT_PROXYTYPE, mwpS3::$proxy['type']);
2101
+ if (isset(mwpS3::$proxy['user'], mwpS3::$proxy['pass']) && mwpS3::$proxy['user'] != null && mwpS3::$proxy['pass'] != null)
2102
+ curl_setopt($curl, CURLOPT_PROXYUSERPWD, sprintf('%s:%s', mwpS3::$proxy['user'], mwpS3::$proxy['pass']));
2103
+ }
2104
+
2105
+ // Headers
2106
+ $headers = array(); $amz = array();
2107
+ foreach ($this->amzHeaders as $header => $value)
2108
+ if (strlen($value) > 0) $headers[] = $header.': '.$value;
2109
+ foreach ($this->headers as $header => $value)
2110
+ if (strlen($value) > 0) $headers[] = $header.': '.$value;
2111
+
2112
+ // Collect AMZ headers for signature
2113
+ foreach ($this->amzHeaders as $header => $value)
2114
+ if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
2115
+
2116
+ // AMZ headers must be sorted
2117
+ if (sizeof($amz) > 0)
2118
+ {
2119
+ usort($amz, array(&$this, '__sortMetaHeadersCmp'));
2120
+ $amz = "\n".implode("\n", $amz);
2121
+ } else $amz = '';
2122
+
2123
+ if (mwpS3::hasAuth())
2124
+ {
2125
+ // Authorization string (CloudFront stringToSign should only contain a date)
2126
+ if ($this->headers['Host'] == 'cloudfront.amazonaws.com')
2127
+ $headers[] = 'Authorization: ' . mwpS3::__getSignature($this->headers['Date']);
2128
+ else
2129
+ {
2130
+ $headers[] = 'Authorization: ' . mwpS3::__getSignature(
2131
+ $this->verb."\n".
2132
+ $this->headers['Content-MD5']."\n".
2133
+ $this->headers['Content-Type']."\n".
2134
+ $this->headers['Date'].$amz."\n".
2135
+ $this->resource
2136
+ );
2137
+ }
2138
+ }
2139
+
2140
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
2141
+ curl_setopt($curl, CURLOPT_HEADER, false);
2142
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
2143
+ curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
2144
+ curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
2145
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
2146
+
2147
+ // Request types
2148
+ switch ($this->verb)
2149
+ {
2150
+ case 'GET': break;
2151
+ case 'PUT': case 'POST': // POST only used for CloudFront
2152
+ if ($this->fp !== false)
2153
+ {
2154
+ curl_setopt($curl, CURLOPT_PUT, true);
2155
+ curl_setopt($curl, CURLOPT_INFILE, $this->fp);
2156
+ if ($this->size >= 0)
2157
+ curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
2158
+ }
2159
+ elseif ($this->data !== false)
2160
+ {
2161
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
2162
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
2163
+ }
2164
+ else
2165
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
2166
+ break;
2167
+ case 'HEAD':
2168
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
2169
+ curl_setopt($curl, CURLOPT_NOBODY, true);
2170
+ break;
2171
+ case 'DELETE':
2172
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
2173
+ break;
2174
+ default: break;
2175
  }
2176
 
2177
+ // Execute, grab errors
2178
+ if (curl_exec($curl))
2179
+ $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
2180
+ else
2181
+ $this->response->error = array(
2182
+ 'code' => curl_errno($curl),
2183
+ 'message' => curl_error($curl),
2184
+ 'resource' => $this->resource
2185
+ );
2186
+
2187
+ @curl_close($curl);
2188
+
2189
+ // Parse body into XML
2190
+ if ($this->response->error === false && isset($this->response->headers['type']) &&
2191
+ $this->response->headers['type'] == 'application/xml' && isset($this->response->body))
2192
+ {
2193
+ $this->response->body = simplexml_load_string($this->response->body);
2194
+
2195
+ // Grab S3 errors
2196
+ if (!in_array($this->response->code, array(200, 204, 206)) &&
2197
+ isset($this->response->body->Code, $this->response->body->Message))
2198
+ {
2199
+ $this->response->error = array(
2200
+ 'code' => (string)$this->response->body->Code,
2201
+ 'message' => (string)$this->response->body->Message
2202
+ );
2203
+ if (isset($this->response->body->Resource))
2204
+ $this->response->error['resource'] = (string)$this->response->body->Resource;
2205
+ unset($this->response->body);
2206
+ }
2207
+ }
2208
+
2209
+ // Clean up file resources
2210
+ if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
2211
+
2212
+ return $this->response;
2213
+ }
2214
+
2215
+ /**
2216
+ * Sort compare for meta headers
2217
+ *
2218
+ * @internal Used to sort x-amz meta headers
2219
+ * @param string $a String A
2220
+ * @param string $b String B
2221
+ * @return integer
2222
+ */
2223
+ private function __sortMetaHeadersCmp($a, $b)
2224
+ {
2225
+ $lenA = strpos($a, ':');
2226
+ $lenB = strpos($b, ':');
2227
+ $minLen = min($lenA, $lenB);
2228
+ $ncmp = strncmp($a, $b, $minLen);
2229
+ if ($lenA == $lenB) return $ncmp;
2230
+ if (0 == $ncmp) return $lenA < $lenB ? -1 : 1;
2231
+ return $ncmp;
2232
+ }
2233
+
2234
+ /**
2235
+ * CURL write callback
2236
+ *
2237
+ * @param resource &$curl CURL resource
2238
+ * @param string &$data Data
2239
+ * @return integer
2240
+ */
2241
+ private function __responseWriteCallback(&$curl, &$data)
2242
+ {
2243
+ if (in_array($this->response->code, array(200, 206)) && $this->fp !== false)
2244
+ return fwrite($this->fp, $data);
2245
+ else
2246
+ $this->response->body .= $data;
2247
+ return strlen($data);
2248
+ }
2249
+
2250
+
2251
+ /**
2252
+ * Check DNS conformity
2253
+ *
2254
+ * @param string $bucket Bucket name
2255
+ * @return boolean
2256
+ */
2257
+ private function __dnsBucketName($bucket)
2258
+ {
2259
+ if (strlen($bucket) > 63 || preg_match("/[^a-z0-9\.-]/", $bucket) > 0) return false;
2260
+ if (strstr($bucket, '-.') !== false) return false;
2261
+ if (strstr($bucket, '..') !== false) return false;
2262
+ if (!preg_match("/^[0-9a-z]/", $bucket)) return false;
2263
+ if (!preg_match("/[0-9a-z]$/", $bucket)) return false;
2264
+ return true;
2265
+ }
2266
+
2267
+
2268
+ /**
2269
+ * CURL header callback
2270
+ *
2271
+ * @param resource &$curl CURL resource
2272
+ * @param string &$data Data
2273
+ * @return integer
2274
+ */
2275
+ private function __responseHeaderCallback(&$curl, &$data)
2276
+ {
2277
+ if (($strlen = strlen($data)) <= 2) return $strlen;
2278
+ if (substr($data, 0, 4) == 'HTTP')
2279
+ $this->response->code = (int)substr($data, 9, 3);
2280
+ else
2281
+ {
2282
+ $data = trim($data);
2283
+ if (strpos($data, ': ') === false) return $strlen;
2284
+ list($header, $value) = explode(': ', $data, 2);
2285
+ if ($header == 'Last-Modified')
2286
+ $this->response->headers['time'] = strtotime($value);
2287
+ elseif ($header == 'Date')
2288
+ $this->response->headers['date'] = strtotime($value);
2289
+ elseif ($header == 'Content-Length')
2290
+ $this->response->headers['size'] = (int)$value;
2291
+ elseif ($header == 'Content-Type')
2292
+ $this->response->headers['type'] = $value;
2293
+ elseif ($header == 'ETag')
2294
+ $this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
2295
+ elseif (preg_match('/^x-amz-meta-.*$/', $header))
2296
+ $this->response->headers[$header] = $value;
2297
+ }
2298
+ return $strlen;
2299
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2300
 
2301
  }
2302
 
2303
+ /**
2304
+ * S3 exception class
2305
+ *
2306
+ * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
2307
+ * @version 0.5.0-dev
2308
+ */
2309
+
2310
  class mwpS3Exception extends Exception {
2311
+ /**
2312
+ * Class constructor
2313
+ *
2314
+ * @param string $message Exception message
2315
+ * @param string $file File in which exception was created
2316
+ * @param string $line Line number on which exception was created
2317
+ * @param int $code Exception code
2318
+ */
2319
+ function __construct($message, $file, $line, $code = 0)
2320
+ {
2321
+ parent::__construct($message, $code);
2322
+ $this->file = $file;
2323
+ $this->line = $line;
2324
+ }
2325
  }
 
plugins/cleanup/cleanup.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  /*************************************************************
3
- *
4
- *
5
- *
6
  * ManageWP Worker Plugin
7
- *
8
- *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
@@ -17,9 +17,9 @@ add_filter('mmb_stats_filter', 'mmb_get_extended_info');
17
 
18
  function mmb_get_extended_info($stats)
19
  {
20
- global $mmb_core;
21
- $params = get_option('mmb_stats_filter');
22
- $filter = isset($params['plugins']['cleanup']) ? $params['plugins']['cleanup'] : array();
23
  $stats['num_revisions'] = mmb_num_revisions($filter['revisions']);
24
  //$stats['num_revisions'] = 5;
25
  $stats['overhead'] = mmb_handle_overhead(false);
@@ -35,11 +35,11 @@ function cleanup_delete_worker($params = array())
35
  {
36
  global $mmb_core;
37
  $revision_params = get_option('mmb_stats_filter');
38
- $revision_filter = isset($revision_params['plugins']['cleanup']) ? $revision_params['plugins']['cleanup'] : array();
39
-
40
  $params_array = explode('_', $params['actions']);
41
  $return_array = array();
42
-
43
  foreach ($params_array as $param) {
44
  switch ($param) {
45
  case 'revision':
@@ -66,11 +66,11 @@ function cleanup_delete_worker($params = array())
66
  default:
67
  break;
68
  }
69
-
70
  }
71
-
72
  unset($params);
73
-
74
  mmb_response($return_array, true);
75
  }
76
 
@@ -79,15 +79,15 @@ function mmb_num_revisions($filter)
79
  global $wpdb;
80
  $sql = "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = 'revision'";
81
  $num_revisions = $wpdb->get_var($sql);
82
- if(isset($filter['num_to_keep']) && !empty($filter['num_to_keep'])){
83
- $num_rev = str_replace("r_","",$filter['num_to_keep']);
84
- if($num_revisions < $num_rev){
85
- return 0;
86
- }
87
- return ($num_revisions - $num_rev);
88
- }else{
89
- return $num_revisions;
90
- }
91
  }
92
 
93
  function mmb_select_all_revisions()
@@ -101,27 +101,27 @@ function mmb_select_all_revisions()
101
  function mmb_delete_all_revisions($filter)
102
  {
103
  global $wpdb, $mmb_core;
104
- $where = '';
105
- if(isset($filter['num_to_keep']) && !empty($filter['num_to_keep'])){
106
- $num_rev = str_replace("r_","",$filter['num_to_keep']);
107
- $select_posts = "SELECT ID FROM $wpdb->posts WHERE post_type = 'revision' ORDER BY post_date DESC LIMIT ".$num_rev;
108
- $select_posts_res = $wpdb->get_results($select_posts);
109
- $notin = '';
110
- $n = 0;
111
- foreach($select_posts_res as $keep_post){
112
- $notin.=$keep_post->ID;
113
- $n++;
114
- if(count($select_posts_res)>$n){
115
- $notin.=',';
116
- }
117
- }
118
- $where = " AND a.ID NOT IN (".$notin.")";
119
- }
120
-
121
  $sql = "DELETE a,b,c FROM $wpdb->posts a LEFT JOIN $wpdb->term_relationships b ON (a.ID = b.object_id) LEFT JOIN $wpdb->postmeta c ON (a.ID = c.post_id) WHERE a.post_type = 'revision'".$where;
122
-
123
- $revisions = $wpdb->query($sql);
124
-
125
  return $revisions;
126
  }
127
 
@@ -141,15 +141,16 @@ function mmb_handle_overhead($clear = false)
141
  $query = 'SHOW TABLE STATUS';
142
  $tables = $wpdb->get_results($query, ARRAY_A);
143
  $total_gain = 0;
144
- $table_string = '';
145
  foreach ($tables as $table) {
146
  if (isset($table['Engine']) && in_array($table['Engine'], array(
147
- 'MyISAM',
148
- 'ISAM',
149
- 'HEAP',
150
- 'MEMORY',
151
- 'ARCHIVE'
152
- ))) {
 
153
  if ($wpdb->base_prefix != $wpdb->prefix) {
154
  if (preg_match('/^' . $wpdb->prefix . '*/Ui', $table['Name'])) {
155
  if ($table['Data_free'] > 0) {
@@ -166,19 +167,27 @@ function mmb_handle_overhead($clear = false)
166
  }
167
  }
168
  } elseif (isset($table['Engine']) && $table['Engine'] == 'InnoDB') {
 
 
 
 
 
 
 
 
169
  //$total_gain += $table['Data_free'] > 100*1024*1024 ? $table['Data_free'] / 1024 : 0;
170
  }
171
  }
172
 
173
  if ($clear) {
174
  $table_string = substr($table_string, 0, strlen($table_string) - 1); //remove last ,
175
-
176
  $table_string = rtrim($table_string);
177
-
178
  $query = "OPTIMIZE TABLE $table_string";
179
-
180
  $optimize = $wpdb->query($query);
181
-
182
  return $optimize === FALSE ? false : true;
183
  } else
184
  return round($total_gain, 3);
@@ -221,4 +230,4 @@ function mmb_get_spam_comments()
221
  $spams = $wpdb->get_results($sql);
222
  return $spams;
223
  }
224
- ?>
1
  <?php
2
  /*************************************************************
3
+ *
4
+ *
5
+ *
6
  * ManageWP Worker Plugin
7
+ *
8
+ *
9
  * Copyright (c) 2011 Prelovac Media
10
  * www.prelovac.com
11
  **************************************************************/
17
 
18
  function mmb_get_extended_info($stats)
19
  {
20
+ global $mmb_core;
21
+ $params = get_option('mmb_stats_filter');
22
+ $filter = isset($params['plugins']['cleanup']) ? $params['plugins']['cleanup'] : array();
23
  $stats['num_revisions'] = mmb_num_revisions($filter['revisions']);
24
  //$stats['num_revisions'] = 5;
25
  $stats['overhead'] = mmb_handle_overhead(false);
35
  {
36
  global $mmb_core;
37
  $revision_params = get_option('mmb_stats_filter');
38
+ $revision_filter = isset($revision_params['plugins']['cleanup']) ? $revision_params['plugins']['cleanup'] : array();
39
+
40
  $params_array = explode('_', $params['actions']);
41
  $return_array = array();
42
+
43
  foreach ($params_array as $param) {
44
  switch ($param) {
45
  case 'revision':
66
  default:
67
  break;
68
  }
69
+
70
  }
71
+
72
  unset($params);
73
+
74
  mmb_response($return_array, true);
75
  }
76
 
79
  global $wpdb;
80
  $sql = "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = 'revision'";
81
  $num_revisions = $wpdb->get_var($sql);
82
+ if(isset($filter['num_to_keep']) && !empty($filter['num_to_keep'])){
83
+ $num_rev = str_replace("r_","",$filter['num_to_keep']);
84
+ if($num_revisions < $num_rev){
85
+ return 0;
86
+ }
87
+ return ($num_revisions - $num_rev);
88
+ }else{
89
+ return $num_revisions;
90
+ }
91
  }
92
 
93
  function mmb_select_all_revisions()
101
  function mmb_delete_all_revisions($filter)
102
  {
103
  global $wpdb, $mmb_core;
104
+ $where = '';
105
+ if(isset($filter['num_to_keep']) && !empty($filter['num_to_keep'])){
106
+ $num_rev = str_replace("r_","",$filter['num_to_keep']);
107
+ $select_posts = "SELECT ID FROM $wpdb->posts WHERE post_type = 'revision' ORDER BY post_date DESC LIMIT ".$num_rev;
108
+ $select_posts_res = $wpdb->get_results($select_posts);
109
+ $notin = '';
110
+ $n = 0;
111
+ foreach($select_posts_res as $keep_post){
112
+ $notin.=$keep_post->ID;
113
+ $n++;
114
+ if(count($select_posts_res)>$n){
115
+ $notin.=',';
116
+ }
117
+ }
118
+ $where = " AND a.ID NOT IN (".$notin.")";
119
+ }
120
+
121
  $sql = "DELETE a,b,c FROM $wpdb->posts a LEFT JOIN $wpdb->term_relationships b ON (a.ID = b.object_id) LEFT JOIN $wpdb->postmeta c ON (a.ID = c.post_id) WHERE a.post_type = 'revision'".$where;
122
+
123
+ $revisions = $wpdb->query($sql);
124
+
125
  return $revisions;
126
  }
127
 
141
  $query = 'SHOW TABLE STATUS';
142
  $tables = $wpdb->get_results($query, ARRAY_A);
143
  $total_gain = 0;
144
+ $table_string = '';
145
  foreach ($tables as $table) {
146
  if (isset($table['Engine']) && in_array($table['Engine'], array(
147
+ 'MyISAM',
148
+ 'ISAM',
149
+ 'HEAP',
150
+ 'MEMORY',
151
+ 'ARCHIVE',
152
+ // 'InnoDB'
153
+ ))) {
154
  if ($wpdb->base_prefix != $wpdb->prefix) {
155
  if (preg_match('/^' . $wpdb->prefix . '*/Ui', $table['Name'])) {
156
  if ($table['Data_free'] > 0) {
167
  }
168
  }
169
  } elseif (isset($table['Engine']) && $table['Engine'] == 'InnoDB') {
170
+ $innodb_file_per_table = $wpdb->get_results("SHOW VARIABLES LIKE 'innodb_file_per_table'");
171
+ if($innodb_file_per_table[0]->Value==="ON")
172
+ {
173
+ if ($table['Data_free'] > 0) {
174
+ $total_gain += $table['Data_free'] / 1024;
175
+ $table_string .= $table['Name'] . ",";
176
+ }
177
+ }
178
  //$total_gain += $table['Data_free'] > 100*1024*1024 ? $table['Data_free'] / 1024 : 0;
179
  }
180
  }
181
 
182
  if ($clear) {
183
  $table_string = substr($table_string, 0, strlen($table_string) - 1); //remove last ,
184
+
185
  $table_string = rtrim($table_string);
186
+
187
  $query = "OPTIMIZE TABLE $table_string";
188
+
189
  $optimize = $wpdb->query($query);
190
+
191
  return $optimize === FALSE ? false : true;
192
  } else
193
  return round($total_gain, 3);
230
  $spams = $wpdb->get_results($sql);
231
  return $spams;
232
  }
233
+ ?>
readme.txt CHANGED
@@ -33,8 +33,14 @@ Check out [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs").
33
 
34
  == Changelog ==
35
 
 
 
 
 
 
 
36
  = 3.9.27 =
37
- - New: SFTP support for backups and clone
38
  - Fix: Database dump for backup tasks with defined socket path or port number in wp-config.php
39
  - Fix: Optimize Wordpress tables before backup
40
  - Fix: Compatibility with Better WP Security
33
 
34
  == Changelog ==
35
 
36
+ = 3.9.28 =
37
+ - New: Control Wordpress Automatic Background Updates for plugins and themes!
38
+ - Fix: Tweaks to SFTP support for backups and clone
39
+ - Fix: Enhancements to Backup and Branding features
40
+
41
+
42
  = 3.9.27 =
43
+ - New: SFTP support for backups and clone!
44
  - Fix: Database dump for backup tasks with defined socket path or port number in wp-config.php
45
  - Fix: Optimize Wordpress tables before backup
46
  - Fix: Compatibility with Better WP Security
security.class.php ADDED
@@ -0,0 +1,440 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by JetBrains PhpStorm.
4
+ * User: nikola milosevic
5
+ * Date: 11/6/13
6
+ * Time: 3:18 PM
7
+ * To change this template use File | Settings | File Templates.
8
+ */
9
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "security.class.php"):
10
+ exit;
11
+ endif;
12
+ class MMB_Security extends MMB_Core
13
+ {
14
+ function __construct()
15
+ {
16
+ parent::__construct();
17
+ }
18
+
19
+
20
+
21
+ function security_check($args)
22
+ {
23
+
24
+ if(MMB_Security::prevent_listing_ok())
25
+ {
26
+ $output["prevent_listing_ok"] = true;
27
+ }
28
+ else
29
+ {
30
+ $output["prevent_listing_ok"] = false;
31
+ }
32
+
33
+ if(MMB_Security::remove_wp_version_ok()){
34
+ $output["remove_wp_version_ok"] = true;
35
+ }
36
+ else
37
+ {
38
+ $output["remove_wp_version_ok"] = false;
39
+ }
40
+
41
+ if(MMB_Security::remove_database_reporting_ok())
42
+ {
43
+ $output["remove_database_reporting_ok"] = true;
44
+ }
45
+ else
46
+ {
47
+ $output["remove_database_reporting_ok"] = false;
48
+ }
49
+
50
+ if(MMB_Security::remove_php_reporting_ok())
51
+ {
52
+ $output["remove_php_reporting_ok"] = true;
53
+ }
54
+ else
55
+ {
56
+ $output["remove_php_reporting_ok"] = false;
57
+ }
58
+
59
+ if( MMB_Security::admin_user_ok())
60
+ {
61
+ $output["admin_user_ok"] = true;
62
+ }
63
+ else
64
+ {
65
+ $output["admin_user_ok"] = false;
66
+ }
67
+
68
+ if( MMB_Security::htaccess_permission_ok())
69
+ {
70
+ $output["htaccess_permission_ok"] = true;
71
+ }
72
+ else
73
+ {
74
+ $output["htaccess_permission_ok"] = false;
75
+ }
76
+ if( MMB_Security::remove_scripts_version_ok()&&MMB_Security::remove_styles_version_ok())
77
+ {
78
+ $output["remove_scripts_and_styles_version_ok"] = true;
79
+ }
80
+ else
81
+ {
82
+ $output["remove_scripts_and_styles_version_ok"] = false;
83
+ }
84
+ if( MMB_Security::file_permission_ok())
85
+ {
86
+ $output["file_permission_ok"] = true;
87
+ }
88
+ else
89
+ {
90
+ $output["file_permission_ok"] = false;
91
+ }
92
+ return $output;
93
+
94
+ }
95
+
96
+ function security_fix_dir_listing($args)
97
+ {
98
+ MMB_Security::prevent_listing();
99
+ return $this->security_check($args);
100
+ }
101
+
102
+ function security_fix_permissions($args)
103
+ {
104
+ MMB_Security::file_permission();
105
+ return $this->security_check($args);
106
+ }
107
+
108
+ function security_fix_php_reporting($args)
109
+ {
110
+ MMB_Security::remove_php_reporting();
111
+ return $this->security_check($args);
112
+ }
113
+
114
+ function security_fix_database_reporting($args)
115
+ {
116
+ MMB_Security::remove_database_reporting();
117
+ return $this->security_check($args);
118
+ }
119
+
120
+ function security_fix_wp_version($args)
121
+ {
122
+ MMB_Security::remove_wp_version();
123
+ return $this->security_check($args);
124
+ }
125
+
126
+ function security_fix_admin_username($args)
127
+ {
128
+ $username = $args[0];
129
+ MMB_Security::change_admin_username($username);
130
+ $scan_res = $this->security_check($args);
131
+ $scan_res["admin_user_ok"] = true;
132
+ return $scan_res;
133
+ }
134
+
135
+ function security_fix_scripts_styles($args)
136
+ {
137
+
138
+ MMB_Security::remove_styles_version();
139
+ MMB_Security::remove_scripts_version();
140
+ return $this->security_check($args);
141
+ }
142
+
143
+ function security_fix_htaccess_permission($args)
144
+ {
145
+ MMB_Security::htaccess_permission();
146
+ return $this->security_check($args);
147
+ }
148
+
149
+ //Prevent listing wp-content, wp-content/plugins, wp-content/themes, wp-content/uploads
150
+ private static $listingDirectories = null;
151
+
152
+ private static function init_listingDirectories()
153
+ {
154
+ if (MMB_Security::$listingDirectories == null)
155
+ {
156
+ $wp_upload_dir = wp_upload_dir();
157
+ MMB_Security::$listingDirectories = array(WP_CONTENT_DIR, WP_PLUGIN_DIR, get_theme_root(), $wp_upload_dir['basedir']);
158
+ }
159
+ }
160
+
161
+ public static function prevent_listing_ok()
162
+ {
163
+ MMB_Security::init_listingDirectories();
164
+ foreach (MMB_Security::$listingDirectories as $directory)
165
+ {
166
+ $file = $directory . DIRECTORY_SEPARATOR . 'index.php';
167
+ if (!file_exists($file))
168
+ {
169
+ return false;
170
+ }
171
+ }
172
+ return true;
173
+ }
174
+
175
+ public static function prevent_listing()
176
+ {
177
+ MMB_Security::init_listingDirectories();
178
+ foreach (MMB_Security::$listingDirectories as $directory)
179
+ {
180
+ $file = $directory . DIRECTORY_SEPARATOR . 'index.php';
181
+ if (!file_exists($file))
182
+ {
183
+ chmod($directory,0777);
184
+ $h = fopen($file, 'w');
185
+ fwrite($h, '<?php die(); ?>');
186
+ fclose($h);
187
+ chmod($directory,0755);
188
+ }
189
+ }
190
+ }
191
+
192
+ //Removed wp-version
193
+ public static function remove_wp_version_ok()
194
+ {
195
+ return !(has_action('wp_head', 'wp_generator') || has_filter('wp_head', 'wp_generator'));
196
+ }
197
+
198
+ public static function remove_wp_version()
199
+ {
200
+ update_option('mwp_remove_wp_version', 'T');
201
+ if (get_option('mwp_remove_wp_version') == 'T')
202
+ {
203
+ remove_action('wp_head', 'wp_generator');
204
+ remove_filter('wp_head', 'wp_generator');
205
+ }
206
+ }
207
+
208
+ //Database error reporting turned on/off
209
+ public static function remove_database_reporting_ok()
210
+ {
211
+ global $wpdb;
212
+ return ($wpdb->show_errors == false);
213
+ }
214
+
215
+ public static function remove_database_reporting()
216
+ {
217
+ global $wpdb;
218
+
219
+ $wpdb->hide_errors();
220
+ $wpdb->suppress_errors();
221
+ }
222
+
223
+ //PHP error reporting turned on/off
224
+ public static function remove_php_reporting_ok()
225
+ {
226
+ return !(((ini_get('display_errors') != 0) && (ini_get('display_errors') != 'off')) || ((ini_get('display_startup_errors') != 0) && (ini_get('display_startup_errors') != 'off')));
227
+ }
228
+
229
+ public static function remove_php_reporting()
230
+ {
231
+ update_option('mwp_remove_php_reporting', 'T');
232
+ if (get_option('mwp_remove_php_reporting') == 'T')
233
+ {
234
+ @error_reporting(0);
235
+ @ini_set('display_errors', 'off');
236
+ @ini_set('display_startup_errors', "off");
237
+ }
238
+ }
239
+
240
+ //Admin user name is not admin
241
+ public static function admin_user_ok()
242
+ {
243
+ $user = get_user_by('login', 'admin');
244
+ return !($user && ($user->wp_user_level == 10 || (isset($user->user_level) && $user->user_level == 10)));
245
+ }
246
+
247
+ public static function change_admin_username($new_username)
248
+ {
249
+ global $wpdb;
250
+ $wpdb->query($wpdb->prepare( "Update {$wpdb->prefix}users SET user_login='%s' where user_login='admin'",$new_username));
251
+
252
+ }
253
+
254
+ //Admin user name is not admin
255
+ public static function htaccess_permission_ok()
256
+ {
257
+ $htaccessPerm = substr(sprintf('%o', fileperms(ABSPATH."/.htaccess")),-4);
258
+ if($htaccessPerm==="0644" || $htaccessPerm==="0444")
259
+ return true;
260
+ else
261
+ return false;
262
+ }
263
+
264
+ public static function htaccess_permission()
265
+ {
266
+ $htaccessPerm = fileperms(ABSPATH."/.htaccess");
267
+ $succ = chmod(ABSPATH."/.htaccess",0644);
268
+ }
269
+
270
+
271
+ public static function remove_scripts_version_ok()
272
+ {
273
+ return (get_option('managewp_remove_scripts_version') == 'T');
274
+
275
+ }
276
+
277
+ public static function remove_script_versions($src)
278
+ {
279
+ update_option('managewp_remove_scripts_version', 'T');
280
+ if (get_option('managewp_remove_scripts_version') == 'T')
281
+ {
282
+ if (strpos($src, '?ver='))
283
+ $src = remove_query_arg('ver', $src);
284
+
285
+ return $src;
286
+ }
287
+ return $src;
288
+ }
289
+
290
+ public static function remove_theme_versions($src)
291
+ {
292
+ update_option('managewp_remove_styles_version', 'T');
293
+ if (get_option('managewp_remove_styles_version') == 'T')
294
+ {
295
+ if (strpos($src, '?ver='))
296
+ $src = remove_query_arg('ver', $src);
297
+
298
+ return $src;
299
+ }
300
+ return $src;
301
+ }
302
+
303
+ public static function remove_scripts_version()
304
+ {
305
+ update_option('managewp_remove_scripts_version', 'T');
306
+ if (get_option('managewp_remove_scripts_version') == 'T')
307
+ {
308
+ global $wp_scripts;
309
+ if (!is_a($wp_scripts, 'WP_Scripts'))
310
+ return;
311
+
312
+ foreach ($wp_scripts->registered as $handle => $script)
313
+ $wp_scripts->registered[$handle]->ver = null;
314
+ }
315
+ }
316
+
317
+ public static function remove_styles_version_ok()
318
+ {
319
+ return (get_option('managewp_remove_styles_version') == 'T');
320
+ }
321
+
322
+ public static function remove_styles_version()
323
+ {
324
+ update_option('managewp_remove_styles_version', 'T');
325
+ if (get_option('managewp_remove_styles_version') == 'T')
326
+ {
327
+ global $wp_styles;
328
+ if (!is_a($wp_styles, 'WP_Styles'))
329
+ return;
330
+
331
+ foreach ($wp_styles->registered as $handle => $style)
332
+ $wp_styles->registered[$handle]->ver = null;
333
+ }
334
+ }
335
+
336
+ public static function file_permission_ok($dir=ABSPATH)
337
+ {
338
+ $files = scandir($dir);
339
+ $dir = rtrim($dir,"/");
340
+ foreach($files as $file)
341
+ {
342
+ if($file!=="."&&$file!==".."&&$file!=="wp-admin"&&$file!=="wp-includes"&&$file!=="plugins"&&$file!=="themes"&&$file!=="uploads"){
343
+ if(is_dir($dir."/".$file))
344
+ {
345
+ $dirPerm = substr(sprintf('%o', fileperms($dir."/".$file)),-4);
346
+ if($dirPerm!=="0755")
347
+ return false;
348
+ $res = MMB_Security::file_permission_ok($dir."/".$file);
349
+ if($res===false)
350
+ return false;
351
+ }
352
+ else
353
+ {
354
+ $filePerm = substr(sprintf('%o', fileperms($dir."/".$file)),-4);
355
+ if($filePerm!=="0644")
356
+ return false;
357
+ }
358
+
359
+ }
360
+ }
361
+ return true;
362
+ }
363
+
364
+ public static function file_permission($dir=ABSPATH)
365
+ {
366
+ $files = scandir($dir);
367
+ $dir = rtrim($dir,"/");
368
+ foreach($files as $file)
369
+ {
370
+ if($file!=="."&&$file!==".."&&$file!=="wp-admin"&&$file!=="wp-includes"&&$file!=="plugins"&&$file!=="themes"&&$file!=="uploads"){
371
+ if(is_dir($dir."/".$file))
372
+ {
373
+ $dirPerm = substr(sprintf('%o', fileperms($dir."/".$file)),-4);
374
+ if($dirPerm!=="0755")
375
+ {
376
+ chmod($dir."/".$file,0755);
377
+ }
378
+
379
+ MMB_Security::file_permission($dir."/".$file);
380
+ }
381
+ else
382
+ {
383
+ $filePerm = substr(sprintf('%o', fileperms($dir."/".$file)),-4);
384
+ if($filePerm!=="0644")
385
+ {
386
+ chmod($dir."/".$file,0644);
387
+ }
388
+ }
389
+ }
390
+
391
+ }
392
+ }
393
+
394
+ public function security_fix_all($args)
395
+ {
396
+ $user_name = $args['new_user_name'];
397
+
398
+ if($args['fix_listing'])
399
+ {
400
+ MMB_Security::security_fix_dir_listing($args);
401
+ }
402
+ if($args['fix_wp_version'])
403
+ {
404
+ MMB_Security::security_fix_wp_version($args);
405
+ }
406
+ if($args['fix_database_reporting'])
407
+ {
408
+ MMB_Security::security_fix_database_reporting($args);
409
+ }
410
+ if($args['fix_php_reporting'])
411
+ {
412
+ MMB_Security::security_fix_php_reporting($args);
413
+ }
414
+ if($args['security_fix_scripts_styles'])
415
+ {
416
+ MMB_Security::security_fix_scripts_styles($args);
417
+ }
418
+ if($args['fix_htaccess_permission'])
419
+ {
420
+ MMB_Security::security_fix_htaccess_permission($args);
421
+ }
422
+ if($args['security_fix_permissions'])
423
+ {
424
+ MMB_Security::security_fix_permissions($args);
425
+ }
426
+ $scan_res = $this->security_check($args);
427
+ if($args['fix_admin_username'])
428
+ {
429
+ $params[] = $user_name;
430
+ MMB_Security::security_fix_admin_username($params);
431
+ $scan_res["admin_user_ok"] = true;
432
+ }
433
+
434
+ return $scan_res;
435
+ }
436
+
437
+
438
+
439
+ }
440
+ ?>
stats.class.php CHANGED
@@ -357,6 +357,15 @@ class MMB_Stats extends MMB_Core
357
  $stats = $this->mmb_parse_action_params('pre_init_stats', $params, $this);
358
  $num = extract($params);
359
 
 
 
 
 
 
 
 
 
 
360
  if ($refresh == 'transient') {
361
  $current = $this->mmb_get_transient('update_core');
362
  if (isset($current->last_checked) || get_option('mmb_forcerefresh')) {
357
  $stats = $this->mmb_parse_action_params('pre_init_stats', $params, $this);
358
  $num = extract($params);
359
 
360
+ if (function_exists( 'w3tc_pgcache_flush' ) || function_exists( 'wp_cache_clear_cache' ) ) {
361
+ $this->mmb_delete_transient('update_core');
362
+ $this->mmb_delete_transient('update_plugins');
363
+ $this->mmb_delete_transient('update_themes');
364
+ @wp_version_check();
365
+ @wp_update_plugins();
366
+ @wp_update_themes();
367
+ }
368
+
369
  if ($refresh == 'transient') {
370
  $current = $this->mmb_get_transient('update_core');
371
  if (isset($current->last_checked) || get_option('mmb_forcerefresh')) {
updater.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MWP_Updater
4
+ {
5
+ private function __construct()
6
+ {
7
+ }
8
+
9
+ public static function isSupported()
10
+ {
11
+ global $wp_version;
12
+
13
+ if (version_compare($wp_version, '3.7', '<')) {
14
+ return false;
15
+ }
16
+
17
+ return true;
18
+ }
19
+
20
+ public static function register()
21
+ {
22
+ if (!self::isSupported()) {
23
+ return;
24
+ }
25
+
26
+ $updater = new self();
27
+
28
+ $autoUpdateCore = get_option('mwp_core_autoupdate');
29
+
30
+ if ($autoUpdateCore === 'never') {
31
+ add_filter('allow_minor_auto_core_updates', '__return_false', 100);
32
+ add_filter('allow_major_auto_core_updates', '__return_false', 100);
33
+ } elseif ($autoUpdateCore === 'minor') {
34
+ add_filter('allow_minor_auto_core_updates', '__return_true', 100);
35
+ add_filter('allow_major_auto_core_updates', '__return_false', 100);
36
+ } elseif ($autoUpdateCore === 'major') {
37
+ add_filter('allow_minor_auto_core_updates', '__return_true', 100);
38
+ add_filter('allow_major_auto_core_updates', '__return_true', 100);
39
+ }
40
+
41
+ add_filter('auto_update_plugin', array($updater, 'updatePlugin'), 100, 2);
42
+ add_filter('auto_update_theme', array($updater, 'updateTheme'), 100, 2);
43
+ add_filter('auto_update_translation', array($updater, 'updateTranslation'), 100, 1);
44
+ }
45
+
46
+ public function updatePlugin($update, $slug)
47
+ {
48
+ if ($slug == 'worker/init.php') {
49
+ return false;
50
+ }
51
+ $alwaysUpdatePlugins = get_option('mwp_global_plugins_autoupdate', 'disabled');
52
+
53
+ if ($alwaysUpdatePlugins === 'enabled') {
54
+ return true;
55
+ }
56
+ $whitelistedPlugins = get_option('mwp_active_autoupdate_plugins', array());
57
+
58
+ if (in_array($slug, $whitelistedPlugins)) {
59
+ return true;
60
+ }
61
+
62
+ return $update;
63
+ }
64
+
65
+ public function updateTheme($update, $slug)
66
+ {
67
+ $alwaysUpdateThemes = get_option('mwp_global_themes_autoupdate', 'disabled');
68
+
69
+ if ($alwaysUpdateThemes === 'enabled') {
70
+ return true;
71
+ }
72
+
73
+ $whitelistedThemes = get_option('mwp_active_autoupdate_themes', array());
74
+
75
+ if (in_array($slug, $whitelistedThemes)) {
76
+ return true;
77
+ }
78
+
79
+ return $update;
80
+ }
81
+
82
+ public function updateTranslation($update)
83
+ {
84
+ $alwaysUpdateTranslations = get_option('mwp_global_translations_autoupdate', 'disabled');
85
+
86
+ if ($alwaysUpdateTranslations === 'enabled') {
87
+ return true;
88
+ }
89
+
90
+ return $update;
91
+ }
92
+
93
+ /**
94
+ * @api
95
+ *
96
+ * @param $args
97
+ *
98
+ * @return array
99
+ */
100
+ public static function setSettings($args)
101
+ {
102
+ if (!self::isSupported()) {
103
+ return array(
104
+ 'error' => "This functionality requires at least WordPress version 3.7",
105
+ );
106
+ }
107
+
108
+ $type = $args['type'];
109
+
110
+ switch ($type) {
111
+ case 'plugins':
112
+ case 'themes':
113
+ self::setAutoUpdateSettings($args['items'], $type);
114
+ break;
115
+ case 'core_never':
116
+ case 'core_minor':
117
+ case 'core_major':
118
+ // Get the last segment, 'core_never' will become 'never'.
119
+ $value = explode('_', $type, 2);
120
+ $value = $value[1];
121
+ update_option('mwp_core_autoupdate', $value);
122
+ break;
123
+ case 'global_plugins_update':
124
+ update_option('mwp_global_plugins_autoupdate', 'enabled');
125
+ break;
126
+ case 'global_plugins_update_disable':
127
+ update_option('mwp_global_plugins_autoupdate', 'disabled');
128
+ break;
129
+ case 'global_themes_update':
130
+ update_option('mwp_global_themes_autoupdate', 'enabled');
131
+ break;
132
+ case 'global_themes_update_disable':
133
+ update_option('mwp_global_themes_autoupdate', 'disabled');
134
+ break;
135
+ case 'global_translations_update':
136
+ update_option('mwp_global_translations_autoupdate', 'enabled');
137
+ break;
138
+ case 'global_translations_update_disable':
139
+ update_option('mwp_global_translations_autoupdate', 'disabled');
140
+ break;
141
+ }
142
+
143
+ return array(
144
+ 'success' => "Successfully updated.",
145
+ );
146
+ }
147
+
148
+ private static function setAutoUpdateSettings($items, $type)
149
+ {
150
+ $return = array();
151
+ foreach ($items as $item) {
152
+ $plugin = plugin_basename($item['path']);
153
+ $current = get_option('mwp_active_autoupdate_' . $type, array());
154
+ if ($item['action'] === 'on') {
155
+ $current[] = $plugin;
156
+ } else {
157
+ $current = array_diff($current, array($plugin));
158
+ }
159
+ sort($current);
160
+ update_option('mwp_active_autoupdate_' . $type, $current);
161
+ $return[$item['name']] = 'OK';
162
+ }
163
+
164
+ return $return;
165
+ }
166
+
167
+ /**
168
+ * @api
169
+ *
170
+ * @param $args
171
+ *
172
+ * @return array
173
+ */
174
+ public static function getSettings($args)
175
+ {
176
+ if (!isset($args['items']) || !is_array($args['items'])) {
177
+ return array(
178
+ 'error' => "No requested items provided (plugins or themes).",
179
+ );
180
+ }
181
+ $items = $args['items'];
182
+
183
+ $return = array();
184
+ $search = empty($args['search']) ? null : $args['search'];
185
+ if (in_array('plugins', $items)) {
186
+ $return['plugins'] = self::getPluginSettings($search);
187
+ }
188
+ if (in_array('themes', $items)) {
189
+ $return['themes'] = self::getThemeSettings($search);
190
+ }
191
+
192
+ return $return;
193
+ }
194
+
195
+ private function getPluginSettings($search = null)
196
+ {
197
+ if (!function_exists('get_plugins')) {
198
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
199
+ }
200
+ $allPlugins = get_plugins();
201
+ $plugins = array(
202
+ 'active' => array(),
203
+ 'inactive' => array(),
204
+ );
205
+
206
+ $whitelistedPlugins = get_option('mwp_active_autoupdate_plugins', array());
207
+ foreach ($allPlugins as $slug => $pluginInfo) {
208
+ if ($slug === 'worker/init.php') {
209
+ continue;
210
+ }
211
+
212
+ if (!empty($search) && stripos($pluginInfo['Name'], $search) === false) {
213
+ continue;
214
+ }
215
+ $key = 'inactive';
216
+
217
+ if (in_array($slug, $whitelistedPlugins)) {
218
+ $key = 'active';
219
+ }
220
+ $plugins[$key][] = array(
221
+ 'path' => $slug,
222
+ 'name' => $pluginInfo['Name'],
223
+ 'version' => $pluginInfo['Version'],
224
+ );
225
+ }
226
+
227
+ return $plugins;
228
+ }
229
+
230
+ private static function getThemeSettings($search = null)
231
+ {
232
+ if (!function_exists('wp_get_themes')) {
233
+ include_once ABSPATH . WPINC . '/theme.php';
234
+ }
235
+
236
+ if (!function_exists('wp_get_themes')) {
237
+ return array();
238
+ }
239
+ $themes = array(
240
+ 'active' => array(),
241
+ 'inactive' => array(),
242
+ );
243
+ $allThemes = wp_get_themes();
244
+
245
+ $whitelistedThemes = get_option('mwp_active_autoupdate_themes', array());
246
+ foreach ($allThemes as $slug => $themeInfo) {
247
+ /** @var WP_Theme $themeInfo */
248
+ if (!empty($search) && stripos($themeInfo->name, $search) === false) {
249
+ continue;
250
+ }
251
+ $key = 'inactive';
252
+
253
+ if (in_array($slug, $whitelistedThemes)) {
254
+ $key = 'active';
255
+ }
256
+ $themes[$key][] = array(
257
+ 'path' => $slug,
258
+ 'name' => $themeInfo->name,
259
+ 'version' => $themeInfo->version,
260
+ 'stylesheet' => $themeInfo->stylesheet,
261
+ );
262
+ }
263
+
264
+ return $themes;
265
+ }
266
+ }
version CHANGED
@@ -1 +1 @@
1
- 3.9.27
1
+ 3.9.28