ManageWP Worker - Version 3.9.20

Version Description

  • New: ManageWP iOS app compatibility
  • New: Perform security and performance test as you add websites
  • New: New comment handling screen
Download this release

Release Info

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

Code changes from version 3.9.19 to 3.9.20

Files changed (22) hide show
  1. api.php +41 -41
  2. backup.class.php +2301 -2286
  3. comment.class.php +251 -44
  4. core.class.php +670 -666
  5. helper.class.php +544 -544
  6. init.php +98 -5
  7. installer.class.php +873 -873
  8. lib/dropbox.oauth.php +1134 -1134
  9. lib/dropbox.php +144 -144
  10. lib/json/JSON.php +806 -806
  11. lib/json/LICENSE +21 -21
  12. lib/s3.php +1967 -1967
  13. link.class.php +181 -181
  14. plugins/cleanup/cleanup.php +221 -221
  15. plugins/extra_html_example/extra_html_example.php +19 -19
  16. plugins/search/search.php +131 -131
  17. post.class.php +688 -684
  18. readme.txt +250 -245
  19. stats.class.php +800 -783
  20. user.class.php +214 -214
  21. version +1 -1
  22. widget.class.php +53 -53
api.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * api.php
5
- *
6
- * ManageWP addons api
7
- *
8
- * Copyright (c) 2011 Prelovac Media
9
- * www.prelovac.com
10
- **************************************************************/
11
- if( !function_exists('mmb_add_action')) :
12
- function mmb_add_action($action = false, $callback = false)
13
- {
14
- if (!$action || !$callback)
15
- return false;
16
-
17
- global $mmb_actions;
18
- mmb_function_exists($callback);
19
-
20
- if (isset($mmb_actions[$action]))
21
- wp_die('Cannot redeclare ManageWP action "' . $action . '".');
22
-
23
- $mmb_actions[$action] = $callback;
24
- }
25
- endif;
26
-
27
- if( !function_exists('mmb_function_exists') ) :
28
- function mmb_function_exists($callback)
29
- {
30
- global $mwp_core;
31
- if (count($callback) === 2) {
32
- if (!method_exists($callback[0], $callback[1]))
33
- wp_die($mwp_core->mwp_dashboard_widget('Information', '', '<p>Class ' . get_class($callback[0]) . ' does not contain <b>"' . $callback[1] . '"</b> function</p>', '', '50%'));
34
- } else {
35
- if (!function_exists($callback))
36
- wp_die($mwp_core->mwp_dashboard_widget('Information', '', '<p>Function <b>"' . $callback . '"</b> does not exists.</p>', '', '50%'));
37
- }
38
- }
39
- endif;
40
-
41
- ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * api.php
5
+ *
6
+ * ManageWP addons api
7
+ *
8
+ * Copyright (c) 2011 Prelovac Media
9
+ * www.prelovac.com
10
+ **************************************************************/
11
+ if( !function_exists('mmb_add_action')) :
12
+ function mmb_add_action($action = false, $callback = false)
13
+ {
14
+ if (!$action || !$callback)
15
+ return false;
16
+
17
+ global $mmb_actions;
18
+ mmb_function_exists($callback);
19
+
20
+ if (isset($mmb_actions[$action]))
21
+ wp_die('Cannot redeclare ManageWP action "' . $action . '".');
22
+
23
+ $mmb_actions[$action] = $callback;
24
+ }
25
+ endif;
26
+
27
+ if( !function_exists('mmb_function_exists') ) :
28
+ function mmb_function_exists($callback)
29
+ {
30
+ global $mwp_core;
31
+ if (count($callback) === 2) {
32
+ if (!method_exists($callback[0], $callback[1]))
33
+ wp_die($mwp_core->mwp_dashboard_widget('Information', '', '<p>Class ' . get_class($callback[0]) . ' does not contain <b>"' . $callback[1] . '"</b> function</p>', '', '50%'));
34
+ } else {
35
+ if (!function_exists($callback))
36
+ wp_die($mwp_core->mwp_dashboard_widget('Information', '', '<p>Function <b>"' . $callback . '"</b> does not exists.</p>', '', '50%'));
37
+ }
38
+ }
39
+ endif;
40
+
41
+ ?>
backup.class.php CHANGED
@@ -1,2287 +1,2302 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * backup.class.php
5
- *
6
- * Manage Backups
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "backup.class.php"):
13
- echo "Sorry but you cannot browse this file directly!";
14
- exit;
15
- endif;
16
- define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
17
- define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
18
-
19
- $zip_errors = array(
20
- 'No error',
21
- 'No error',
22
- 'Unexpected end of zip file',
23
- 'A generic error in the zipfile format was detected.',
24
- 'zip was unable to allocate itself memory',
25
- 'A severe error in the zipfile format was detected',
26
- 'Entry too large to be split with zipsplit',
27
- 'Invalid comment format',
28
- 'zip -T failed or out of memory',
29
- 'The user aborted zip prematurely',
30
- 'zip encountered an error while using a temp file',
31
- 'Read or seek error',
32
- 'zip has nothing to do',
33
- 'Missing or empty zip file',
34
- 'Error writing to a file',
35
- 'zip was unable to create a file to write to',
36
- 'bad command line parameters',
37
- 'no error',
38
- 'zip could not open a specified file to read'
39
- );
40
- $unzip_errors = array(
41
- 'No error',
42
- 'One or more warning errors were encountered, but processing completed successfully anyway',
43
- 'A generic error in the zipfile format was detected',
44
- 'A severe error in the zipfile format was detected.',
45
- 'unzip was unable to allocate itself memory.',
46
- 'unzip was unable to allocate memory, or encountered an encryption error',
47
- 'unzip was unable to allocate memory during decompression to disk',
48
- 'unzip was unable allocate memory during in-memory decompression',
49
- 'unused',
50
- 'The specified zipfiles were not found',
51
- 'Bad command line parameters',
52
- 'No matching files were found',
53
- 50 => 'The disk is (or was) full during extraction',
54
- 51 => 'The end of the ZIP archive was encountered prematurely.',
55
- 80 => 'The user aborted unzip prematurely.',
56
- 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
57
- 82 => 'No files were found due to bad decryption password(s)'
58
- );
59
-
60
-
61
- class MMB_Backup extends MMB_Core
62
- {
63
- var $site_name;
64
- var $statuses;
65
- var $tasks;
66
- var $s3;
67
- var $ftp;
68
- var $dropbox;
69
- function __construct()
70
- {
71
- parent::__construct();
72
- $this->site_name = str_replace(array(
73
- "_",
74
- "/",
75
- "~"
76
- ), array(
77
- "",
78
- "-",
79
- "-"
80
- ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
81
- $this->statuses = array(
82
- 'db_dump' => 1,
83
- 'db_zip' => 2,
84
- 'files_zip' => 3,
85
- 's3' => 4,
86
- 'dropbox' => 5,
87
- 'ftp' => 6,
88
- 'email' => 7,
89
- 'finished' => 100
90
- );
91
- $this->tasks = get_option('mwp_backup_tasks');
92
- }
93
-
94
- function set_memory()
95
- {
96
- $changed = array('execution_time' => 0, 'memory_limit' => 0);
97
-
98
- $memory_limit = trim(ini_get('memory_limit'));
99
- $last = strtolower(substr($memory_limit, -1));
100
-
101
- if($last == 'g')
102
- $memory_limit = ((int) $memory_limit)*1024;
103
- else if($last == 'm')
104
- $memory_limit = (int) $memory_limit;
105
- if($last == 'k')
106
- $memory_limit = ((int) $memory_limit)/1024;
107
-
108
- if ( $memory_limit < 384 ) {
109
- @ini_set('memory_limit', '384M');
110
- $changed['memory_limit'] = 1;
111
- }
112
-
113
- if ( (int) @ini_get('max_execution_time') < 600 ) {
114
- @set_time_limit(600); //ten minutes
115
- $changed['execution_time'] = 1;
116
- }
117
-
118
- return $changed;
119
-
120
- }
121
-
122
- function get_backup_settings()
123
- {
124
- $backup_settings = get_option('mwp_backup_tasks');
125
-
126
- if (!empty($backup_settings))
127
- return $backup_settings;
128
- else
129
- return false;
130
- }
131
-
132
- function set_backup_task($params)
133
- {
134
- //$params => [$task_name, $args, $error]
135
- if (!empty($params)) {
136
-
137
- //Make sure backup cron job is set
138
- if (!wp_next_scheduled('mwp_backup_tasks')) {
139
- wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
140
- }
141
-
142
- extract($params);
143
-
144
- //$before = $this->get_backup_settings();
145
- $before = $this->tasks;
146
- if (!$before || empty($before))
147
- $before = array();
148
-
149
- if (isset($args['remove'])) {
150
- unset($before[$task_name]);
151
- $return = array(
152
- 'removed' => true
153
- );
154
- } else {
155
- if (isset($params['account_info']) && is_array($params['account_info'])) { //only if sends from master first time(secure data)
156
- $args['account_info'] = $account_info;
157
- }
158
-
159
- $before[$task_name]['task_args'] = $args;
160
- if (strlen($args['schedule']))
161
- $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
162
-
163
- $return = $before[$task_name];
164
- }
165
-
166
- //Update with error
167
- if (isset($error)) {
168
- if (is_array($error)) {
169
- $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
170
- } else {
171
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
172
- }
173
- }
174
-
175
- if ($time) { //set next result time before backup
176
- if (is_array($before[$task_name]['task_results'])) {
177
- $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
178
- }
179
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
180
- }
181
-
182
- $this->update_tasks($before);
183
- //update_option('mwp_backup_tasks', $before);
184
-
185
- if ($task_name == 'Backup Now') {
186
- $result = $this->backup($args, $task_name);
187
- $backup_settings = $this->tasks;
188
-
189
- if (is_array($result) && array_key_exists('error', $result)) {
190
- $return = $result;
191
- } else {
192
- $return = $backup_settings[$task_name];
193
- }
194
- }
195
- return $return;
196
- }
197
-
198
-
199
-
200
- return false;
201
- }
202
-
203
- //Cron check
204
- function check_backup_tasks()
205
- {
206
-
207
- $this->check_cron_remove();
208
-
209
- $settings = $this->tasks;
210
- if (is_array($settings) && !empty($settings)) {
211
- foreach ($settings as $task_name => $setting) {
212
- if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
213
- //if ($setting['task_args']['next'] && $_GET['force_backup']) {
214
- if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
215
- //Check orphan task
216
- $check_data = array(
217
- 'task_name' => $task_name,
218
- 'task_id' => $setting['task_args']['task_id'],
219
- 'site_key' => $setting['task_args']['site_key']
220
- );
221
-
222
- $check = $this->validate_task($check_data, $setting['task_args']['url']);
223
-
224
- }
225
-
226
- $update = array(
227
- 'task_name' => $task_name,
228
- 'args' => $settings[$task_name]['task_args']
229
- );
230
-
231
-
232
- if($check != 'paused'){
233
- $update['time'] = time();
234
- }
235
-
236
- //Update task with next schedule
237
- $this->set_backup_task($update);
238
-
239
- if($check == 'paused'){
240
- continue;
241
- }
242
-
243
-
244
- $result = $this->backup($setting['task_args'], $task_name);
245
- $error = '';
246
- if (is_array($result) && array_key_exists('error', $result)) {
247
- $error = $result;
248
- $this->set_backup_task(array(
249
- 'task_name' => $task_name,
250
- 'args' => $settings[$task_name]['task_args'],
251
- 'error' => $error
252
- ));
253
- } else {
254
- $error = '';
255
- }
256
- break; //Only one backup per cron
257
- }
258
- }
259
- }
260
-
261
- }
262
-
263
- function task_now($task_name){
264
-
265
- $settings = $this->tasks;
266
- if(!array_key_exists($task_name,$settings)){
267
- return array('error' => $task_name." does not exist.");
268
- } else {
269
- $setting = $settings[$task_name];
270
- }
271
-
272
- $this->set_backup_task(array(
273
- 'task_name' => $task_name,
274
- 'args' => $settings[$task_name]['task_args'],
275
- 'time' => time()
276
- ));
277
-
278
- //Run backup
279
- $result = $this->backup($setting['task_args'], $task_name);
280
-
281
- //Check for error
282
- if (is_array($result) && array_key_exists('error', $result)) {
283
- $this->set_backup_task(array(
284
- 'task_name' => $task_name,
285
- 'args' => $settings[$task_name]['task_args'],
286
- 'error' => $result
287
- ));
288
- return $result;
289
- } else {
290
- return $this->get_backup_stats();
291
- }
292
- }
293
-
294
-
295
-
296
- /*
297
- * If Task Name not set then it's manual backup
298
- * Backup args:
299
- * type -> db, full
300
- * what -> daily, weekly, monthly
301
- * account_info -> ftp, amazons3, dropbox
302
- * exclude-> array of paths to exclude from backup
303
- */
304
-
305
- function backup($args, $task_name = false)
306
- {
307
-
308
- $this->_log($this->tasks);
309
-
310
- if (!$args || empty($args))
311
- return false;
312
-
313
- extract($args); //extract settings
314
-
315
- //Try increase memory limit and execution time
316
- $this->set_memory();
317
-
318
-
319
-
320
- //Remove old backup(s)
321
- $this->remove_old_backups($task_name);
322
-
323
-
324
-
325
- $new_file_path = MWP_BACKUP_DIR;
326
-
327
- if (!file_exists($new_file_path)) {
328
- if (!mkdir($new_file_path, 0755, true))
329
- return array(
330
- 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
331
- );
332
- }
333
-
334
- @file_put_contents($new_file_path . '/index.php', ''); //safe
335
-
336
- //Prepare .zip file name
337
- $hash = md5(time());
338
- $label = $type ? $type : 'manual';
339
- $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
340
- $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
341
-
342
- //Optimize tables?
343
- if (isset($optimize_tables) && !empty($optimize_tables)) {
344
- $this->optimize_tables();
345
- }
346
-
347
- //What to backup - db or full?
348
- if (trim($what) == 'db') {
349
- //Take database backup
350
- $this->update_status($task_name, $this->statuses['db_dump']);
351
- $db_result = $this->backup_db();
352
- if ($db_result == false) {
353
- return array(
354
- 'error' => 'Failed to backup database.'
355
- );
356
- } else if (is_array($db_result) && isset($db_result['error'])) {
357
- return array(
358
- 'error' => $db_result['error']
359
- );
360
- } else {
361
- $this->update_status($task_name, $this->statuses['db_dump'], true);
362
- $this->update_status($task_name, $this->statuses['db_zip']);
363
-
364
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
365
- $comp_level = $disable_comp ? '-0' : '-1';
366
-
367
- chdir(MWP_BACKUP_DIR);
368
- $zip = $this->get_zip();
369
- $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
370
- ob_start();
371
- $result = $this->mmb_exec($command);
372
- ob_get_clean();
373
- if (!$result) { // fallback to pclzip
374
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
375
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
376
- $archive = new PclZip($backup_file);
377
- if ($disable_comp) {
378
- $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
379
- } else {
380
- $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
381
- }
382
- @unlink($db_result);
383
- @rmdir(MWP_DB_DIR);
384
- if (!$result) {
385
- return array(
386
- 'error' => 'Failed to zip database (pclZip - ' . $archive->error_code . '): .' . $archive->error_string
387
- );
388
- }
389
- }
390
-
391
- @unlink($db_result);
392
- @rmdir(MWP_DB_DIR);
393
- if (!$result) {
394
- return array(
395
- 'error' => 'Failed to zip database.'
396
- );
397
- }
398
- $this->update_status($task_name, $this->statuses['db_zip'], true);
399
- }
400
- } elseif (trim($what) == 'full') {
401
- $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
402
- if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
403
- return array(
404
- 'error' => $content_backup['error']
405
- );
406
- }
407
- }
408
-
409
- //Update backup info
410
- if ($task_name) {
411
- //backup task (scheduled)
412
- $backup_settings = $this->tasks;
413
- $paths = array();
414
- $size = ceil(filesize($backup_file) / 1024);
415
-
416
- if ($size > 1000) {
417
- $paths['size'] = ceil($size / 1024) . "Mb";
418
- } else {
419
- $paths['size'] = $size . 'kb';
420
- }
421
-
422
- if ($task_name != 'Backup Now') {
423
- if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
424
- $paths['server'] = array(
425
- 'file_path' => $backup_file,
426
- 'file_url' => $backup_url
427
- );
428
- }
429
- } else {
430
- $paths['server'] = array(
431
- 'file_path' => $backup_file,
432
- 'file_url' => $backup_url
433
- );
434
- }
435
-
436
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
437
- $paths['ftp'] = basename($backup_url);
438
- }
439
-
440
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
441
- $paths['amazons3'] = basename($backup_url);
442
- }
443
-
444
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
445
- $paths['dropbox'] = basename($backup_url);
446
- }
447
-
448
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
449
- $paths['email'] = basename($backup_url);
450
- }
451
-
452
- $temp = $backup_settings[$task_name]['task_results'];
453
- $temp = array_values($temp);
454
- $paths['time'] = time();
455
-
456
- if ($task_name != 'Backup Now') {
457
- $paths['status'] = $temp[count($temp) - 1]['status'];
458
- $temp[count($temp) - 1] = $paths;
459
-
460
- } else {
461
- $temp[count($temp)] = $paths;
462
- }
463
-
464
- $backup_settings[$task_name]['task_results'] = $temp;
465
- $this->update_tasks($backup_settings);
466
- //update_option('mwp_backup_tasks', $backup_settings);
467
- }
468
-
469
-
470
- //Additional: Email, ftp, amazon_s3, dropbox...
471
-
472
- if ($task_name != 'Backup Now') {
473
- if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
474
- $this->update_status($task_name, $this->statuses['ftp']);
475
- $account_info['mwp_ftp']['backup_file'] = $backup_file;
476
- $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
477
-
478
- if ($ftp_result !== true && $del_host_file) {
479
- @unlink($backup_file);
480
- }
481
-
482
- if (is_array($ftp_result) && isset($ftp_result['error'])) {
483
- return $ftp_result;
484
- }
485
- $this->wpdb_reconnect();
486
- $this->update_status($task_name, $this->statuses['ftp'], true);
487
- }
488
-
489
- if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
490
- $this->update_status($task_name, $this->statuses['s3']);
491
- $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
492
- $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
493
- if ($amazons3_result !== true && $del_host_file) {
494
- @unlink($backup_file);
495
- }
496
- if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
497
- return $amazons3_result;
498
- }
499
- $this->wpdb_reconnect();
500
- $this->update_status($task_name, $this->statuses['s3'], true);
501
- }
502
-
503
- if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
504
- $this->update_status($task_name, $this->statuses['dropbox']);
505
- $account_info['mwp_dropbox']['backup_file'] = $backup_file;
506
- $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
507
- if ($dropbox_result !== true && $del_host_file) {
508
- @unlink($backup_file);
509
- }
510
-
511
- if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
512
- return $dropbox_result;
513
- }
514
- $this->wpdb_reconnect();
515
- $this->update_status($task_name, $this->statuses['dropbox'], true);
516
- }
517
-
518
- if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
519
- $this->update_status($task_name, $this->statuses['email']);
520
- $account_info['mwp_email']['task_name'] = $task_name;
521
- $account_info['mwp_email']['file_path'] = $backup_file;
522
-
523
- $email_result = $this->email_backup($account_info['mwp_email']);
524
- if (is_array($email_result) && isset($email_result['error'])) {
525
- return $email_result;
526
- }
527
- $this->update_status($task_name, $this->statuses['email'], true);
528
- }
529
-
530
- if ($del_host_file) {
531
- @unlink($backup_file);
532
- }
533
-
534
- } //end additional
535
-
536
- //$this->update_status($task_name,$this->statuses['finished'],true);
537
- return $backup_url; //Return url to backup file
538
- }
539
-
540
- function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
541
- {
542
- global $zip_errors;
543
- $sys = substr(PHP_OS, 0, 3);
544
-
545
- $this->update_status($task_name, $this->statuses['db_dump']);
546
- $db_result = $this->backup_db();
547
-
548
- if ($db_result == false) {
549
- return array(
550
- 'error' => 'Failed to backup database.'
551
- );
552
- } else if (is_array($db_result) && isset($db_result['error'])) {
553
- return array(
554
- 'error' => $db_result['error']
555
- );
556
- }
557
-
558
- $this->update_status($task_name, $this->statuses['db_dump'], true);
559
- $this->update_status($task_name, $this->statuses['db_zip']);
560
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
561
- $comp_level = $disable_comp ? '-0' : '-1';
562
-
563
- $zip = $this->get_zip();
564
- //Add database file
565
- chdir(MWP_BACKUP_DIR);
566
- $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
567
- ob_start();
568
- $result = $this->mmb_exec($command);
569
- ob_get_clean();
570
-
571
-
572
- if (!$result) {
573
- $this->_log("DB zip fallback to pclZip");
574
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
575
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
576
- $archive = new PclZip($backup_file);
577
-
578
- if ($disable_comp) {
579
- $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
580
- } else {
581
- $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
582
- }
583
-
584
- @unlink($db_result);
585
- @rmdir(MWP_DB_DIR);
586
-
587
- if (!$result_db) {
588
- return array(
589
- 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
590
- );
591
- }
592
- }
593
-
594
- @unlink($db_result);
595
- @rmdir(MWP_DB_DIR);
596
-
597
- $this->update_status($task_name, $this->statuses['db_zip'], true);
598
-
599
-
600
- //Always remove backup folders
601
- $remove = array(
602
- trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
603
- trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
604
- );
605
-
606
- //Exclude paths
607
- $exclude_data = "-x";
608
-
609
- $exclude_file_data = '';
610
-
611
- if (!empty($exclude)) {
612
- foreach ($exclude as $data) {
613
- if (is_dir(ABSPATH . $data)) {
614
- if ($sys == 'WIN')
615
- $exclude_data .= " $data/*.*";
616
- else
617
- $exclude_data .= " '$data/*'";
618
-
619
-
620
- } else {
621
- if ($sys == 'WIN'){
622
- if(file_exists(ABSPATH . $data)){
623
- $exclude_data .= " $data";
624
- $exclude_file_data .= " $data";
625
- }
626
- } else {
627
- if(file_exists(ABSPATH . $data)){
628
- $exclude_data .= " '$data'";
629
- $exclude_file_data .= " '$data'";
630
- }
631
- }
632
- }
633
- }
634
- }
635
-
636
- if($exclude_file_data){
637
- $exclude_file_data = "-x".$exclude_file_data;
638
- }
639
-
640
- foreach ($remove as $data) {
641
- if ($sys == 'WIN')
642
- $exclude_data .= " $data/*.*";
643
- else
644
- $exclude_data .= " '$data/*'";
645
- }
646
-
647
- //Include paths by default
648
- $add = array(
649
- trim(WPINC),
650
- trim(basename(WP_CONTENT_DIR)),
651
- "wp-admin"
652
- );
653
-
654
- $include_data = ". -i";
655
- foreach ($add as $data) {
656
- if ($sys == 'WIN')
657
- $include_data .= " $data/*.*";
658
- else
659
- $include_data .= " '$data/*'";
660
- }
661
-
662
- //Additional includes?
663
- if (!empty($include)) {
664
- foreach ($include as $data) {
665
- if ($data) {
666
- if ($sys == 'WIN')
667
- $include_data .= " $data/*.*";
668
- else
669
- $include_data .= " '$data/*'";
670
- }
671
- }
672
- }
673
-
674
- $this->update_status($task_name, $this->statuses['files_zip']);
675
- chdir(ABSPATH);
676
- ob_start();
677
- $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
678
- $result_f = $this->mmb_exec($command, false, true);
679
- if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
680
- $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
681
- $result_d = $this->mmb_exec($command, false, true);
682
- if ($result_d && $result_d != 18) {
683
- @unlink($backup_file);
684
- if ($result_d > 0 && $result_d < 18)
685
- return array(
686
- 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
687
- );
688
- else
689
- return array(
690
- 'error' => 'Failed to archive files.'
691
- );
692
- }
693
- }
694
- ob_get_clean();
695
-
696
- if ($result_f && $result_f != 18) { //Try pclZip
697
- $this->_log("Files zip fallback to pclZip");
698
- if (!isset($archive)) {
699
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
700
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
701
- $archive = new PclZip($backup_file);
702
- }
703
-
704
- //Include paths
705
- $include_data = array();
706
- if (!empty($include)) {
707
- foreach ($include as $data) {
708
- if ($data && file_exists(ABSPATH . $data))
709
- $include_data[] = ABSPATH . $data . '/';
710
- }
711
- }
712
-
713
- foreach ($add as $data) {
714
- if (file_exists(ABSPATH . $data))
715
- $include_data[] = ABSPATH . $data . '/';
716
- }
717
-
718
- //Include root files
719
- if ($handle = opendir(ABSPATH)) {
720
- while (false !== ($file = readdir($handle))) {
721
- if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
722
- $include_data[] = ABSPATH . $file;
723
- }
724
- }
725
- closedir($handle);
726
- }
727
-
728
- if ($disable_comp) {
729
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION);
730
- } else {
731
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH);
732
- }
733
- if (!$result) {
734
- @unlink($backup_file);
735
- return array(
736
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
737
- );
738
- }
739
-
740
- //Now exclude paths
741
- $exclude_data = array();
742
- if (!empty($exclude)) {
743
- foreach ($exclude as $data) {
744
- if (is_dir(ABSPATH . $data))
745
- $exclude_data[] = $data . '/';
746
- else
747
- $exclude_data[] = $data;
748
- }
749
- }
750
-
751
- foreach ($remove as $rem) {
752
- $exclude_data[] = $rem . '/';
753
- }
754
-
755
- $result_excl = $archive->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
756
- if (!$result_excl) {
757
- @unlink($backup_file);
758
- return array(
759
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
760
- );
761
- }
762
-
763
- }
764
-
765
- //Reconnect
766
- $this->wpdb_reconnect();
767
-
768
- $this->update_status($task_name, $this->statuses['files_zip'], true);
769
- return true;
770
- }
771
-
772
-
773
- function backup_db()
774
- {
775
- $db_folder = MWP_DB_DIR . '/';
776
- if (!file_exists($db_folder)) {
777
- if (!mkdir($db_folder, 0755, true))
778
- return array(
779
- 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
780
- );
781
- }
782
-
783
- $file = $db_folder . DB_NAME . '.sql';
784
- $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
785
- return $result;
786
- }
787
-
788
- function backup_db_dump($file)
789
- {
790
- global $wpdb;
791
- $paths = $this->check_mysql_paths();
792
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
793
- $command = $brace . $paths['mysqldump'] . $brace . ' --force --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --add-drop-table --skip-lock-tables "' . DB_NAME . '" > ' . $brace . $file . $brace;
794
- ob_start();
795
- $result = $this->mmb_exec($command);
796
- ob_get_clean();
797
-
798
- if (!$result) { // Fallback to php
799
- $this->_log("DB dump fallback to php");
800
- $result = $this->backup_db_php($file);
801
- return $result;
802
- }
803
-
804
- if (filesize($file) == 0 || !is_file($file) || !$result) {
805
- @unlink($file);
806
- return false;
807
- } else {
808
- return $file;
809
- }
810
- }
811
-
812
- function backup_db_php($file)
813
- {
814
- global $wpdb;
815
- $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
816
- foreach ($tables as $table) {
817
- //drop existing table
818
- $dump_data = "DROP TABLE IF EXISTS $table[0];";
819
- //create table
820
- $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
821
- $dump_data .= "\n\n" . $create_table[1] . ";\n\n";
822
-
823
- $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
824
- if ($count > 100)
825
- $count = ceil($count / 100);
826
- else if ($count > 0)
827
- $count = 1;
828
-
829
- for ($i = 0; $i < $count; $i++) {
830
- $low_limit = $i * 100;
831
- $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
832
- $rows = $wpdb->get_results($qry, ARRAY_A);
833
- if (is_array($rows)) {
834
- foreach ($rows as $row) {
835
- //insert single row
836
- $dump_data .= "INSERT INTO $table[0] VALUES(";
837
- $num_values = count($row);
838
- $j = 1;
839
- foreach ($row as $value) {
840
- $value = addslashes($value);
841
- $value = preg_replace("/\n/Ui", "\\n", $value);
842
- $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
843
- $j++;
844
- unset($value);
845
- }
846
- $dump_data .= ");\n";
847
- }
848
- }
849
- }
850
- $dump_data .= "\n\n\n";
851
-
852
- unset($rows);
853
- file_put_contents($file, $dump_data, FILE_APPEND);
854
- unset($dump_data);
855
- }
856
-
857
- if (filesize($file) == 0 || !is_file($file)) {
858
- @unlink($file);
859
- return array(
860
- 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
861
- );
862
- }
863
-
864
- return $file;
865
-
866
- }
867
-
868
- function restore($args)
869
- {
870
- $this->_log($args);
871
- global $wpdb;
872
- if (empty($args)) {
873
- return false;
874
- }
875
-
876
- extract($args);
877
- $this->set_memory();
878
-
879
- $unlink_file = true; //Delete file after restore
880
-
881
- //Detect source
882
- if ($backup_url) {
883
- //This is for clone (overwrite)
884
- include_once ABSPATH . 'wp-admin/includes/file.php';
885
- $backup_file = download_url($backup_url);
886
- if (is_wp_error($backup_file)) {
887
- return array(
888
- 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
889
- );
890
- }
891
- $what = 'full';
892
- } else {
893
- $tasks = $this->tasks;
894
- $task = $tasks[$task_name];
895
- if (isset($task['task_results'][$result_id]['server'])) {
896
- $backup_file = $task['task_results'][$result_id]['server']['file_path'];
897
- $unlink_file = false; //Don't delete file if stored on server
898
- } elseif (isset($task['task_results'][$result_id]['ftp'])) {
899
- $ftp_file = $task['task_results'][$result_id]['ftp'];
900
- $args = $task['task_args']['account_info']['mwp_ftp'];
901
- $args['backup_file'] = $ftp_file;
902
- $backup_file = $this->get_ftp_backup($args);
903
- if ($backup_file == false) {
904
- return array(
905
- 'error' => 'Failed to download file from FTP.'
906
- );
907
- }
908
- } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
909
- $amazons3_file = $task['task_results'][$result_id]['amazons3'];
910
- $args = $task['task_args']['account_info']['mwp_amazon_s3'];
911
- $args['backup_file'] = $amazons3_file;
912
- $backup_file = $this->get_amazons3_backup($args);
913
- if ($backup_file == false) {
914
- return array(
915
- 'error' => 'Failed to download file from Amazon S3.'
916
- );
917
- }
918
- } elseif(isset($task['task_results'][$result_id]['dropbox'])){
919
- $dropbox_file = $task['task_results'][$result_id]['dropbox'];
920
- $args = $task['task_args']['account_info']['mwp_dropbox'];
921
- $args['backup_file'] = $dropbox_file;
922
- $backup_file = $this->get_dropbox_backup($args);
923
-
924
- if ($backup_file == false) {
925
- return array(
926
- 'error' => 'Failed to download file from Dropbox.'
927
- );
928
- }
929
- }
930
-
931
- $what = $tasks[$task_name]['task_args']['what'];
932
- }
933
-
934
- $this->wpdb_reconnect();
935
-
936
- if ($backup_file && file_exists($backup_file)) {
937
- if ($overwrite) {
938
- //Keep old db credentials before overwrite
939
- if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
940
- @unlink($backup_file);
941
- return array(
942
- 'error' => 'Error creating wp-config. Please check your write permissions.'
943
- );
944
- }
945
-
946
- $db_host = DB_HOST;
947
- $db_user = DB_USER;
948
- $db_password = DB_PASSWORD;
949
- $home = rtrim(get_option('home'), "/");
950
- $site_url = get_option('site_url');
951
-
952
- $clone_options = array();
953
- if (trim($clone_from_url) || trim($mwp_clone)) {
954
-
955
- $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
956
- $clone_options['_worker_public_key'] = get_option('_worker_public_key');
957
- $clone_options['_action_message_id'] = get_option('_action_message_id');
958
-
959
- }
960
- $clone_options['upload_path'] = get_option('upload_path');
961
- $clone_options['upload_url_path'] = get_option('upload_url_path');
962
-
963
- $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
964
- $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
965
- $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
966
-
967
-
968
- } else {
969
- $restore_options = array();
970
- $restore_options['mwp_notifications'] = get_option('mwp_notifications');
971
- $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
972
- $restore_options['user_hit_count'] = get_option('user_hit_count');
973
- }
974
-
975
-
976
- chdir(ABSPATH);
977
- $unzip = $this->get_unzip();
978
- $command = "$unzip -o $backup_file";
979
- ob_start();
980
- $result = $this->mmb_exec($command);
981
- ob_get_clean();
982
-
983
- if (!$result) { //fallback to pclzip
984
- $this->_log("Files uznip fallback to pclZip");
985
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
986
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
987
- $archive = new PclZip($backup_file);
988
- $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
989
- }
990
-
991
- if ($unlink_file) {
992
- @unlink($backup_file);
993
- }
994
-
995
- if (!$result) {
996
- return array(
997
- 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
998
- );
999
- }
1000
-
1001
- $db_result = $this->restore_db();
1002
-
1003
- if (!$db_result) {
1004
- return array(
1005
- 'error' => 'Error restoring database.'
1006
- );
1007
- } else if(is_array($db_result) && isset($db_result['error'])){
1008
- return array(
1009
- 'error' => $db_result['error']
1010
- );
1011
- }
1012
-
1013
- } else {
1014
- return array(
1015
- 'error' => 'Error restoring. Cannot find backup file.'
1016
- );
1017
- }
1018
-
1019
- $this->wpdb_reconnect();
1020
-
1021
- //Replace options and content urls
1022
- if ($overwrite) {
1023
- //Get New Table prefix
1024
- $new_table_prefix = trim($this->get_table_prefix());
1025
- //Retrieve old wp_config
1026
- @unlink(ABSPATH . 'wp-config.php');
1027
- //Replace table prefix
1028
- $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
1029
-
1030
- foreach ($lines as $line) {
1031
- if (strstr($line, '$table_prefix')) {
1032
- $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
1033
- }
1034
- file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
1035
- }
1036
-
1037
- @unlink(ABSPATH . 'mwp-temp-wp-config.php');
1038
-
1039
- //Replace options
1040
- $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
1041
- $old = $wpdb->get_var($wpdb->prepare($query));
1042
- $old = rtrim($old, "/");
1043
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'home'";
1044
- $wpdb->query($wpdb->prepare($query));
1045
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'siteurl'";
1046
- $wpdb->query($wpdb->prepare($query));
1047
- //Replace content urls
1048
- $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, '$old','$home') WHERE post_content REGEXP 'src=\"(.*)$old(.*)\"' OR post_content REGEXP 'href=\"(.*)$old(.*)\"'";
1049
- $wpdb->query($wpdb->prepare($query));
1050
-
1051
- if (trim($new_password)) {
1052
- $new_password = wp_hash_password($new_password);
1053
- }
1054
- if (!trim($clone_from_url) && !trim($mwp_clone)) {
1055
- if ($new_user && $new_password) {
1056
- $query = "UPDATE " . $new_table_prefix . "users SET user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$old_user'";
1057
- $wpdb->query($wpdb->prepare($query));
1058
- }
1059
- } else {
1060
- if ($clone_from_url) {
1061
- if ($new_user && $new_password) {
1062
- $query = "UPDATE " . $new_table_prefix . "users SET user_pass = '$new_password' WHERE user_login = '$new_user'";
1063
- $wpdb->query($wpdb->prepare($query));
1064
- }
1065
- }
1066
-
1067
- if ($mwp_clone) {
1068
- if ($admin_email) {
1069
- //Clean Install
1070
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$admin_email' WHERE option_name = 'admin_email'";
1071
- $wpdb->query($wpdb->prepare($query));
1072
- $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
1073
- $temp_user = $wpdb->get_row($query);
1074
- if (!empty($temp_user)) {
1075
- $query = "UPDATE " . $new_table_prefix . "users SET user_email='$admin_email', user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$temp_user->user_login'";
1076
- $wpdb->query($wpdb->prepare($query));
1077
- }
1078
-
1079
- }
1080
- }
1081
- }
1082
-
1083
- if (is_array($clone_options) && !empty($clone_options)) {
1084
- foreach ($clone_options as $key => $option) {
1085
- if (!empty($key)) {
1086
- $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = '$key'";
1087
- $res = $wpdb->get_var($query);
1088
- if ($res == false) {
1089
- $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES('$option','$key')";
1090
- $wpdb->query($wpdb->prepare($query));
1091
- } else {
1092
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$option' WHERE option_name = '$key'";
1093
- $wpdb->query($wpdb->prepare($query));
1094
- }
1095
- }
1096
- }
1097
- }
1098
-
1099
- //Remove hit count
1100
- $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'user_hit_count'";
1101
- $wpdb->query($wpdb->prepare($query));
1102
-
1103
- //Check for .htaccess permalinks update
1104
- $this->replace_htaccess($home);
1105
- } else {
1106
-
1107
- //restore worker options
1108
- if (is_array($restore_options) && !empty($restore_options)) {
1109
- foreach ($restore_options as $key => $option) {
1110
- update_option($key,$option);
1111
- }
1112
- }
1113
-
1114
- }
1115
-
1116
-
1117
-
1118
-
1119
- return true;
1120
- }
1121
-
1122
- function restore_db()
1123
- {
1124
- global $wpdb;
1125
- $paths = $this->check_mysql_paths();
1126
- $file_path = ABSPATH . 'mwp_db';
1127
- @chmod($file_path,0755);
1128
- $file_name = glob($file_path . '/*.sql');
1129
- $file_name = $file_name[0];
1130
-
1131
- if(!$file_name){
1132
- return array('error' => 'Cannot access database file.');
1133
- }
1134
-
1135
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1136
- $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
1137
-
1138
- ob_start();
1139
- $result = $this->mmb_exec($command);
1140
- ob_get_clean();
1141
- if (!$result) {
1142
- $this->_log('DB restore fallback to PHP');
1143
- //try php
1144
- $this->restore_db_php($file_name);
1145
- }
1146
-
1147
-
1148
- @unlink($file_name);
1149
- return true;
1150
- }
1151
-
1152
- function restore_db_php($file_name)
1153
- {
1154
- global $wpdb;
1155
- $current_query = '';
1156
- // Read in entire file
1157
- $lines = file($file_name);
1158
- // Loop through each line
1159
- foreach ($lines as $line) {
1160
- // Skip it if it's a comment
1161
- if (substr($line, 0, 2) == '--' || $line == '')
1162
- continue;
1163
-
1164
- // Add this line to the current query
1165
- $current_query .= $line;
1166
- // If it has a semicolon at the end, it's the end of the query
1167
- if (substr(trim($line), -1, 1) == ';') {
1168
- // Perform the query
1169
- $result = $wpdb->query($current_query);
1170
- if ($result === false)
1171
- return false;
1172
- // Reset temp variable to empty
1173
- $current_query = '';
1174
- }
1175
- }
1176
-
1177
- @unlink($file_name);
1178
- return true;
1179
- }
1180
-
1181
- function get_table_prefix()
1182
- {
1183
- $lines = file(ABSPATH . 'wp-config.php');
1184
- foreach ($lines as $line) {
1185
- if (strstr($line, '$table_prefix')) {
1186
- $pattern = "/(\'|\")[^(\'|\")]*/";
1187
- preg_match($pattern, $line, $matches);
1188
- $prefix = substr($matches[0], 1);
1189
- return $prefix;
1190
- break;
1191
- }
1192
- }
1193
- return 'wp_'; //default
1194
- }
1195
-
1196
- function optimize_tables()
1197
- {
1198
- global $wpdb;
1199
- $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
1200
- $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1201
- foreach ($tables as $table) {
1202
- if (in_array($table['Engine'], array(
1203
- 'MyISAM',
1204
- 'ISAM',
1205
- 'HEAP',
1206
- 'MEMORY',
1207
- 'ARCHIVE'
1208
- )))
1209
- $table_string .= $table['Name'] . ",";
1210
- elseif ($table['Engine'] == 'InnoDB') {
1211
- $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1212
- }
1213
- }
1214
-
1215
- $table_string = rtrim($table_string);
1216
- $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1217
-
1218
- return $optimize ? true : false;
1219
- }
1220
-
1221
- ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1222
- function check_mysql_paths()
1223
- {
1224
- global $wpdb;
1225
- $paths = array(
1226
- 'mysql' => '',
1227
- 'mysqldump' => ''
1228
- );
1229
- if (substr(PHP_OS, 0, 3) == 'WIN') {
1230
- $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1231
- if ($mysql_install) {
1232
- $install_path = str_replace('\\', '/', $mysql_install->Value);
1233
- $paths['mysql'] = $install_path . 'bin/mysql.exe';
1234
- $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1235
- } else {
1236
- $paths['mysql'] = 'mysql.exe';
1237
- $paths['mysqldump'] = 'mysqldump.exe';
1238
- }
1239
- } else {
1240
- $paths['mysql'] = $this->mmb_exec('which mysql', true);
1241
- if (empty($paths['mysql']))
1242
- $paths['mysql'] = 'mysql'; // try anyway
1243
-
1244
- $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1245
- if (empty($paths['mysqldump']))
1246
- $paths['mysqldump'] = 'mysqldump'; // try anyway
1247
-
1248
- }
1249
-
1250
-
1251
- return $paths;
1252
- }
1253
-
1254
- //Check if exec, system, passthru functions exist
1255
- function check_sys()
1256
- {
1257
- if ($this->mmb_function_exists('exec'))
1258
- return 'exec';
1259
-
1260
- if ($this->mmb_function_exists('system'))
1261
- return 'system';
1262
-
1263
- if ($this->mmb_function_exists('passhtru'))
1264
- return 'passthru';
1265
-
1266
- return false;
1267
-
1268
- }
1269
-
1270
- function mmb_exec($command, $string = false, $rawreturn = false)
1271
- {
1272
- if ($command == '')
1273
- return false;
1274
-
1275
- if ($this->mmb_function_exists('exec')) {
1276
- $log = @exec($command, $output, $return);
1277
- $this->_log("Type: exec");
1278
- $this->_log("Command: ".$command);
1279
- $this->_log("Return: ".$return);
1280
- if ($string)
1281
- return $log;
1282
- if ($rawreturn)
1283
- return $return;
1284
-
1285
- return $return ? false : true;
1286
- } elseif ($this->mmb_function_exists('system')) {
1287
- $log = @system($command, $return);
1288
- $this->_log("Type: system");
1289
- $this->_log("Command: ".$command);
1290
- $this->_log("Return: ".$return);
1291
- if ($string)
1292
- return $log;
1293
-
1294
- if ($rawreturn)
1295
- return $return;
1296
-
1297
- return $return ? false : true;
1298
- } elseif ($this->mmb_function_exists('passthru') && !$string) {
1299
- $log = passthru($command, $return);
1300
- $this->_log("Type: passthru");
1301
- $this->_log("Command: ".$command);
1302
- $this->_log("Return: ".$return);
1303
- if ($rawreturn)
1304
- return $return;
1305
-
1306
- return $return ? false : true;
1307
- }
1308
-
1309
- if ($rawreturn)
1310
- return -1;
1311
-
1312
- return false;
1313
- }
1314
-
1315
- function get_zip()
1316
- {
1317
- $zip = $this->mmb_exec('which zip', true);
1318
- if (!$zip)
1319
- $zip = "zip";
1320
- return $zip;
1321
- }
1322
-
1323
- function get_unzip()
1324
- {
1325
- $unzip = $this->mmb_exec('which unzip', true);
1326
- if (!$unzip)
1327
- $unzip = "unzip";
1328
- return $unzip;
1329
- }
1330
-
1331
- function check_backup_compat()
1332
- {
1333
-
1334
- $reqs = array();
1335
- if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1336
- $reqs['Server OS']['status'] = 'Linux (or compatible)';
1337
- $reqs['Server OS']['pass'] = true;
1338
- } else {
1339
- $reqs['Server OS']['status'] = 'Windows';
1340
- $reqs['Server OS']['pass'] = true;
1341
- $pass = false;
1342
- }
1343
- $reqs['PHP Version']['status'] = phpversion();
1344
- if ((float) phpversion() >= 5.1) {
1345
- $reqs['PHP Version']['pass'] = true;
1346
- } else {
1347
- $reqs['PHP Version']['pass'] = false;
1348
- $pass = false;
1349
- }
1350
-
1351
-
1352
- if (is_writable(WP_CONTENT_DIR)) {
1353
- $reqs['Backup Folder']['status'] = "writable";
1354
- $reqs['Backup Folder']['pass'] = true;
1355
- } else {
1356
- $reqs['Backup Folder']['status'] = "not writable";
1357
- $reqs['Backup Folder']['pass'] = false;
1358
- }
1359
-
1360
-
1361
- $file_path = MWP_BACKUP_DIR;
1362
- $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1363
-
1364
- if ($func = $this->check_sys()) {
1365
- $reqs['Execute Function']['status'] = $func;
1366
- $reqs['Execute Function']['pass'] = true;
1367
- } else {
1368
- $reqs['Execute Function']['status'] = "not found";
1369
- $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1370
- $reqs['Execute Function']['pass'] = false;
1371
- }
1372
- $reqs['Zip']['status'] = $this->get_zip();
1373
-
1374
- $reqs['Zip']['pass'] = true;
1375
-
1376
-
1377
-
1378
- $reqs['Unzip']['status'] = $this->get_unzip();
1379
-
1380
- $reqs['Unzip']['pass'] = true;
1381
-
1382
- $paths = $this->check_mysql_paths();
1383
-
1384
- if (!empty($paths['mysqldump'])) {
1385
- $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1386
- $reqs['MySQL Dump']['pass'] = true;
1387
- } else {
1388
- $reqs['MySQL Dump']['status'] = "not found";
1389
- $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1390
- $reqs['MySQL Dump']['pass'] = false;
1391
- }
1392
-
1393
- $exec_time = ini_get('max_execution_time');
1394
- $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1395
- $reqs['Execution time']['pass'] = true;
1396
-
1397
- $mem_limit = ini_get('memory_limit');
1398
- $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1399
- $reqs['Memory limit']['pass'] = true;
1400
-
1401
- $changed = $this->set_memory();
1402
- if($changed['execution_time']){
1403
- $exec_time = ini_get('max_execution_time');
1404
- $reqs['Execution time']['status'] .= $exec_time ? ' (will try '.$exec_time . 's)' : ' (unknown)';
1405
- }
1406
- if($changed['memory_limit']){
1407
- $mem_limit = ini_get('memory_limit');
1408
- $reqs['Memory limit']['status'] .= $mem_limit ? ' (will try '.$mem_limit.')' : ' (unknown)';
1409
- }
1410
-
1411
- return $reqs;
1412
- }
1413
-
1414
- function email_backup($args)
1415
- {
1416
- $email = $args['email'];
1417
-
1418
- if (!is_email($email)) {
1419
- return array(
1420
- 'error' => 'Your email (' . $email . ') is not correct'
1421
- );
1422
- }
1423
- $backup_file = $args['file_path'];
1424
- $task_name = isset($args['task_name']) ? $args['task_name'] : '';
1425
- if (file_exists($backup_file) && $email) {
1426
- $attachments = array(
1427
- $backup_file
1428
- );
1429
- $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
1430
- $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
1431
- ob_start();
1432
- $result = wp_mail($email, $subject, $subject, $headers, $attachments);
1433
- ob_end_clean();
1434
-
1435
- }
1436
-
1437
- if (!$result) {
1438
- return array(
1439
- 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
1440
- );
1441
- }
1442
- return true;
1443
-
1444
- }
1445
-
1446
- function ftp_backup($args)
1447
- {
1448
- extract($args);
1449
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1450
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
1451
- if ($ftp_ssl) {
1452
- if (function_exists('ftp_ssl_connect')) {
1453
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1454
- } else {
1455
- return array(
1456
- 'error' => 'FTPS disabled: Please enable ftp_ssl_connect in PHP',
1457
- 'partial' => 1
1458
- );
1459
- }
1460
- } else {
1461
- if (function_exists('ftp_connect')) {
1462
- $conn_id = ftp_connect($ftp_hostname,$port);
1463
- if ($conn_id === false) {
1464
- return array(
1465
- 'error' => 'Failed to connect to ' . $ftp_hostname,
1466
- 'partial' => 1
1467
- );
1468
- }
1469
- } else {
1470
- return array(
1471
- 'error' => 'FTP disabled: Please enable ftp_connect in PHP',
1472
- 'partial' => 1
1473
- );
1474
- }
1475
- }
1476
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1477
- if ($login === false) {
1478
- return array(
1479
- 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1480
- 'partial' => 1
1481
- );
1482
- }
1483
-
1484
- if($ftp_passive){
1485
- @ftp_pasv($conn_id,true);
1486
- }
1487
-
1488
- @ftp_mkdir($conn_id, $ftp_remote_folder);
1489
- if ($ftp_site_folder) {
1490
- $ftp_remote_folder .= '/' . $this->site_name;
1491
- }
1492
- @ftp_mkdir($conn_id, $ftp_remote_folder);
1493
-
1494
- $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1495
- if ($upload === false) { //Try ascii
1496
- $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1497
- }
1498
- ftp_close($conn_id);
1499
-
1500
- if ($upload === false) {
1501
- return array(
1502
- 'error' => 'Failed to upload file to FTP. Please check your specified path.',
1503
- 'partial' => 1
1504
- );
1505
- }
1506
-
1507
- return true;
1508
- }
1509
-
1510
- function remove_ftp_backup($args)
1511
- {
1512
- extract($args);
1513
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1514
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
1515
- if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1516
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1517
- } else if (function_exists('ftp_connect')) {
1518
- $conn_id = ftp_connect($ftp_hostname,$port);
1519
- }
1520
-
1521
- if ($conn_id) {
1522
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1523
- if ($ftp_site_folder)
1524
- $ftp_remote_folder .= '/' . $this->site_name;
1525
-
1526
- if($ftp_passive){
1527
- @ftp_pasv($conn_id,true);
1528
- }
1529
-
1530
- $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1531
-
1532
- ftp_close($conn_id);
1533
- }
1534
-
1535
- }
1536
-
1537
- function get_ftp_backup($args)
1538
- {
1539
- extract($args);
1540
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1541
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
1542
- if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1543
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1544
-
1545
- } else if (function_exists('ftp_connect')) {
1546
- $conn_id = ftp_connect($ftp_hostname,$port);
1547
- if ($conn_id === false) {
1548
- return false;
1549
- }
1550
- }
1551
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1552
- if ($login === false) {
1553
- return false;
1554
- } else {
1555
- }
1556
-
1557
- if ($ftp_site_folder)
1558
- $ftp_remote_folder .= '/' . $this->site_name;
1559
-
1560
- if($ftp_passive){
1561
- @ftp_pasv($conn_id,true);
1562
- }
1563
-
1564
- $temp = ABSPATH . 'mwp_temp_backup.zip';
1565
- $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1566
- if ($get === false) {
1567
- return false;
1568
- } else {
1569
- }
1570
- ftp_close($conn_id);
1571
-
1572
- return $temp;
1573
- }
1574
-
1575
- function dropbox_backup($args)
1576
- {
1577
-
1578
- extract($args);
1579
-
1580
- if(isset($consumer_secret) && !empty($consumer_secret)){
1581
- //New way
1582
- require_once('lib/dropbox.oauth.php');
1583
-
1584
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1585
- $dropbox->setOAuthToken($oauth_token);
1586
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1587
-
1588
- if ($dropbox_site_folder == true)
1589
- $dropbox_destination .= '/' . $this->site_name;
1590
-
1591
- try{
1592
-
1593
- $dropbox->filesPost($dropbox_destination, $backup_file,true);
1594
-
1595
- } catch(Exception $e){
1596
- return array(
1597
- 'error' => 'Dropbox upload error. '.$e->getMessage()
1598
- );
1599
- }
1600
-
1601
- return true;
1602
-
1603
- } else {
1604
- //old way
1605
- require_once('lib/dropbox.php');
1606
-
1607
- //$email, $password, $backup_file, $destination, $dropbox_site_folder
1608
-
1609
- $size = ceil(filesize($backup_file) / 1024);
1610
- if ($size > 300000) {
1611
- return array(
1612
- 'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
1613
- 'partial' => 1
1614
- );
1615
- }
1616
-
1617
- if ($dropbox_site_folder == true)
1618
- $dropbox_destination .= '/' . $this->site_name;
1619
-
1620
- try {
1621
- $uploader = new DropboxUploader($dropbox_username, $dropbox_password);
1622
- $uploader->upload($backup_file, $dropbox_destination);
1623
- }
1624
- catch (Exception $e) {
1625
- return array(
1626
- 'error' => $e->getMessage(),
1627
- 'partial' => 1
1628
- );
1629
- }
1630
-
1631
- return true;
1632
- }
1633
-
1634
- }
1635
-
1636
- function remove_dropbox_backup($args){
1637
- extract($args);
1638
- if(isset($consumer_secret) && !empty($consumer_secret)){
1639
- //New way
1640
- require_once('lib/dropbox.oauth.php');
1641
-
1642
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1643
- $dropbox->setOAuthToken($oauth_token);
1644
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1645
-
1646
- if ($dropbox_site_folder == true)
1647
- $dropbox_destination .= '/' . $this->site_name;
1648
-
1649
- try{
1650
- $dropbox->fileopsDelete($dropbox_destination.'/'.$backup_file, true);
1651
- } catch(Exception $e){
1652
-
1653
- }
1654
- }
1655
- }
1656
-
1657
- function get_dropbox_backup($args){
1658
- extract($args);
1659
-
1660
- if(isset($consumer_secret) && !empty($consumer_secret)){
1661
- //New way
1662
- require_once('lib/dropbox.oauth.php');
1663
-
1664
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
1665
- $dropbox->setOAuthToken($oauth_token);
1666
- $dropbox->setOAuthTokenSecret($oauth_token_secret);
1667
-
1668
- if ($dropbox_site_folder == true)
1669
- $dropbox_destination .= '/' . $this->site_name;
1670
-
1671
- $temp = ABSPATH . 'mwp_temp_backup.zip';
1672
-
1673
- try{
1674
- $file = $dropbox->filesGet($dropbox_destination.'/'.$backup_file, true);
1675
-
1676
- if(isset($file['data']) && !empty($file['data']) )
1677
- $stream = base64_decode($file['data']);
1678
- else
1679
- return false;
1680
-
1681
- $handle = @fopen($temp, 'w+');
1682
- $result = fwrite($handle,$stream);
1683
- fclose($handle);
1684
-
1685
- if($result)
1686
- return $temp;
1687
- else
1688
- return false;
1689
-
1690
- } catch(Exception $e){
1691
-
1692
-
1693
- return false;
1694
- }
1695
-
1696
- } else {
1697
- return false;
1698
- }
1699
-
1700
-
1701
- }
1702
-
1703
- function amazons3_backup($args)
1704
- {
1705
- if ($this->mmb_function_exists('curl_init')) {
1706
- require_once('lib/s3.php');
1707
- extract($args);
1708
-
1709
- if ($as3_site_folder == true)
1710
- $as3_directory .= '/' . $this->site_name;
1711
-
1712
- $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1713
- try{
1714
- $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1715
- if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
1716
- return true;
1717
- } else {
1718
-
1719
- return array(
1720
- 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
1721
- 'partial' => 1
1722
- );
1723
- }
1724
-
1725
- }catch (Exception $e){
1726
- $err = $e->getMessage();
1727
- if($err){
1728
- return array(
1729
- 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
1730
- );
1731
- } else {
1732
- return array(
1733
- 'error' => 'Failed to upload to Amazon S3.'
1734
- );
1735
- }
1736
- }
1737
-
1738
- } else {
1739
- return array(
1740
- 'error' => 'You cannot use Amazon S3 on your server. Please enable curl extension first.',
1741
- 'partial' => 1
1742
- );
1743
- }
1744
- }
1745
-
1746
- function remove_amazons3_backup($args)
1747
- {
1748
- if ($this->mmb_function_exists('curl_init')) {
1749
- require_once('lib/s3.php');
1750
- extract($args);
1751
- if ($as3_site_folder == true)
1752
- $as3_directory .= '/' . $this->site_name;
1753
- $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1754
- try{
1755
- $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1756
- $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
1757
- } catch (Exception $e){
1758
-
1759
- }
1760
- }
1761
- }
1762
-
1763
- function get_amazons3_backup($args)
1764
- {
1765
- require_once('lib/s3.php');
1766
- extract($args);
1767
- $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1768
- $temp = '';
1769
- try{
1770
- $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1771
- if ($as3_site_folder == true)
1772
- $as3_directory .= '/' . $this->site_name;
1773
-
1774
- $temp = ABSPATH . 'mwp_temp_backup.zip';
1775
- $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
1776
- } catch (Exception $e){
1777
- return $temp;
1778
- }
1779
- return $temp;
1780
- }
1781
-
1782
- function schedule_next($type, $schedule)
1783
- {
1784
- $schedule = explode("|", $schedule);
1785
-
1786
- if (empty($schedule))
1787
- return false;
1788
- switch ($type) {
1789
-
1790
- case 'daily':
1791
-
1792
- if (isset($schedule[1]) && $schedule[1]) {
1793
- $delay_time = $schedule[1] * 60;
1794
- }
1795
-
1796
- $current_hour = date("H");
1797
- $schedule_hour = $schedule[0];
1798
- if ($current_hour >= $schedule_hour)
1799
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
1800
- else
1801
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1802
- break;
1803
-
1804
-
1805
- case 'weekly':
1806
- if (isset($schedule[2]) && $schedule[2]) {
1807
- $delay_time = $schedule[2] * 60;
1808
- }
1809
- $current_weekday = date('w');
1810
- $schedule_weekday = $schedule[1];
1811
- $current_hour = date("H");
1812
- $schedule_hour = $schedule[0];
1813
-
1814
- if ($current_weekday > $schedule_weekday)
1815
- $weekday_offset = 7 - ($week_day - $task_schedule[1]);
1816
- else
1817
- $weekday_offset = $schedule_weekday - $current_weekday;
1818
-
1819
-
1820
- if (!$weekday_offset) { //today is scheduled weekday
1821
- if ($current_hour >= $schedule_hour)
1822
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
1823
- else
1824
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1825
- } else {
1826
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
1827
- }
1828
-
1829
- break;
1830
-
1831
- case 'monthly':
1832
- if (isset($schedule[2]) && $schedule[2]) {
1833
- $delay_time = $schedule[2] * 60;
1834
- }
1835
- $current_monthday = date('j');
1836
- $schedule_monthday = $schedule[1];
1837
- $current_hour = date("H");
1838
- $schedule_hour = $schedule[0];
1839
-
1840
- if ($current_monthday > $schedule_monthday) {
1841
- $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1842
- } else if ($current_monthday < $schedule_monthday) {
1843
- $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1844
- } else if ($current_monthday == $schedule_monthday) {
1845
- if ($current_hour >= $schedule_hour)
1846
- $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1847
- else
1848
- $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1849
- break;
1850
- }
1851
-
1852
- break;
1853
- default:
1854
- break;
1855
- }
1856
-
1857
- if (isset($delay_time) && $delay_time) {
1858
- $time += $delay_time;
1859
- }
1860
-
1861
- return $time;
1862
-
1863
- }
1864
-
1865
- //Parse task arguments for info on master
1866
- function get_backup_stats()
1867
- {
1868
- $stats = array();
1869
- $tasks = $this->tasks;
1870
- if (is_array($tasks) && !empty($tasks)) {
1871
- foreach ($tasks as $task_name => $info) {
1872
- if (is_array($info['task_results']) && !empty($info['task_results'])) {
1873
- foreach ($info['task_results'] as $key => $result) {
1874
- if (isset($result['server']) && !isset($result['error'])) {
1875
- if (!file_exists($result['server']['file_path'])) {
1876
- $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
1877
- }
1878
- }
1879
- }
1880
- }
1881
- if (is_array($info['task_results']))
1882
- $stats[$task_name] = array_values($info['task_results']);
1883
-
1884
- }
1885
- }
1886
- return $stats;
1887
- }
1888
-
1889
- function get_next_schedules()
1890
- {
1891
- $stats = array();
1892
- $tasks = $this->tasks;
1893
- if (is_array($tasks) && !empty($tasks)) {
1894
- foreach ($tasks as $task_name => $info) {
1895
- $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
1896
- }
1897
- }
1898
- return $stats;
1899
- }
1900
-
1901
- function remove_old_backups($task_name)
1902
- {
1903
-
1904
- //Check for previous failed backups first
1905
- $this->cleanup();
1906
-
1907
- //Remove by limit
1908
- $backups = $this->tasks;
1909
- if ($task_name == 'Backup Now') {
1910
- $num = 0;
1911
- } else {
1912
- $num = 1;
1913
- }
1914
-
1915
-
1916
- if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
1917
- //how many to remove ?
1918
- $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
1919
- for ($i = 0; $i < $remove_num; $i++) {
1920
- //Remove from the server
1921
- if (isset($backups[$task_name]['task_results'][$i]['server'])) {
1922
- @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
1923
- }
1924
-
1925
- //Remove from ftp
1926
- if (isset($backups[$task_name]['task_results'][$i]['ftp']) && isset($backups[$task_name]['task_args']['account_info']['mwp_ftp'])) {
1927
- $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
1928
- $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
1929
- $args['backup_file'] = $ftp_file;
1930
- $this->remove_ftp_backup($args);
1931
- }
1932
-
1933
- if (isset($backups[$task_name]['task_results'][$i]['amazons3']) && isset($backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
1934
- $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
1935
- $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1936
- $args['backup_file'] = $amazons3_file;
1937
- $this->remove_amazons3_backup($args);
1938
- }
1939
-
1940
- if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
1941
- //To do: dropbox remove
1942
- $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
1943
- $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
1944
- $args['backup_file'] = $dropbox_file;
1945
- $this->remove_dropbox_backup($args);
1946
- }
1947
-
1948
- //Remove database backup info
1949
- unset($backups[$task_name]['task_results'][$i]);
1950
-
1951
- } //end foreach
1952
-
1953
- if (is_array($backups[$task_name]['task_results']))
1954
- $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
1955
- else
1956
- $backups[$task_name]['task_results']=array();
1957
-
1958
- $this->update_tasks($backups);
1959
- //update_option('mwp_backup_tasks', $backups);
1960
- }
1961
- }
1962
-
1963
- /**
1964
- * Delete specified backup
1965
- * Args: $task_name, $result_id
1966
- */
1967
-
1968
- function delete_backup($args)
1969
- {
1970
- if (empty($args))
1971
- return false;
1972
- extract($args);
1973
-
1974
- $tasks = $this->tasks;
1975
- $task = $tasks[$task_name];
1976
- $backups = $task['task_results'];
1977
- $backup = $backups[$result_id];
1978
-
1979
- if (isset($backup['server'])) {
1980
- @unlink($backup['server']['file_path']);
1981
- }
1982
-
1983
- //Remove from ftp
1984
- if (isset($backup['ftp'])) {
1985
- $ftp_file = $backup['ftp'];
1986
- $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
1987
- $args['backup_file'] = $ftp_file;
1988
- $this->remove_ftp_backup($args);
1989
- }
1990
-
1991
- if (isset($backup['amazons3'])) {
1992
- $amazons3_file = $backup['amazons3'];
1993
- $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1994
- $args['backup_file'] = $amazons3_file;
1995
- $this->remove_amazons3_backup($args);
1996
- }
1997
-
1998
- if (isset($backup['dropbox'])) {
1999
- $dropbox_file = $backup['dropbox'];
2000
- $args = $tasks[$task_name]['task_args']['account_info']['mwp_dropbox'];
2001
- $args['backup_file'] = $dropbox_file;
2002
- $this->remove_dropbox_backup($args);
2003
- }
2004
-
2005
- unset($backups[$result_id]);
2006
-
2007
- if (count($backups)) {
2008
- $tasks[$task_name]['task_results'] = $backups;
2009
- } else {
2010
- unset($tasks[$task_name]['task_results']);
2011
- }
2012
-
2013
- $this->update_tasks($tasks);
2014
- //update_option('mwp_backup_tasks', $tasks);
2015
- return true;
2016
-
2017
- }
2018
-
2019
- function cleanup()
2020
- {
2021
- $tasks = $this->tasks;
2022
- $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
2023
- $backup_folder_new = MWP_BACKUP_DIR . '/';
2024
- $files = glob($backup_folder . "*");
2025
- $new = glob($backup_folder_new . "*");
2026
-
2027
- //Failed db files first
2028
- $db_folder = MWP_DB_DIR . '/';
2029
- $db_files = glob($db_folder . "*");
2030
- if (is_array($db_files) && !empty($db_files)) {
2031
- foreach ($db_files as $file) {
2032
- @unlink($file);
2033
- }
2034
- @rmdir(MWP_DB_DIR);
2035
- }
2036
-
2037
-
2038
- //clean_old folder?
2039
- if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
2040
- foreach ($files as $file) {
2041
- @unlink($file);
2042
- }
2043
- @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
2044
- @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
2045
- }
2046
-
2047
-
2048
- foreach ($new as $b) {
2049
- $files[] = $b;
2050
- }
2051
- $deleted = array();
2052
-
2053
- if (is_array($files) && count($files)) {
2054
- $results = array();
2055
- if (!empty($tasks)) {
2056
- foreach ((array) $tasks as $task) {
2057
- if (isset($task['task_results']) && count($task['task_results'])) {
2058
- foreach ($task['task_results'] as $backup) {
2059
- if (isset($backup['server'])) {
2060
- $results[] = $backup['server']['file_path'];
2061
- }
2062
- }
2063
- }
2064
- }
2065
- }
2066
-
2067
- $num_deleted = 0;
2068
- foreach ($files as $file) {
2069
- if (!in_array($file, $results) && basename($file) != 'index.php') {
2070
- @unlink($file);
2071
- $deleted[] = basename($file);
2072
- $num_deleted++;
2073
- }
2074
- }
2075
- }
2076
-
2077
-
2078
-
2079
- return $deleted;
2080
- }
2081
-
2082
-
2083
- function remote_backup_now($args)
2084
- {
2085
- $this->set_memory();
2086
-
2087
- if (!empty($args))
2088
- extract($args);
2089
-
2090
- $tasks = $this->tasks;
2091
- $task = $tasks['Backup Now'];
2092
-
2093
- if (!empty($task)) {
2094
- extract($task['task_args']);
2095
- }
2096
-
2097
- $results = $task['task_results'];
2098
-
2099
- if (is_array($results) && count($results)) {
2100
- $backup_file = $results[count($results) - 1]['server']['file_path'];
2101
- }
2102
-
2103
- if ($backup_file && file_exists($backup_file)) {
2104
- //FTP, Amazon S3 or Dropbox
2105
- if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
2106
- $account_info['mwp_ftp']['backup_file'] = $backup_file;
2107
- $return = $this->ftp_backup($account_info['mwp_ftp']);
2108
- }
2109
-
2110
- if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
2111
- $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
2112
- $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
2113
- }
2114
-
2115
- if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
2116
- $account_info['mwp_dropbox']['backup_file'] = $backup_file;
2117
- $return = $this->dropbox_backup($account_info['mwp_dropbox']);
2118
- }
2119
-
2120
- if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
2121
- $account_info['mwp_email']['file_path'] = $backup_file;
2122
- $account_info['mwp_email']['task_name'] = 'Backup Now';
2123
- $return = $this->email_backup($account_info['mwp_email']);
2124
- }
2125
-
2126
-
2127
- if ($return == true && $del_host_file) {
2128
- @unlink($backup_file);
2129
- unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
2130
- $this->update_tasks($tasks);
2131
- //update_option('mwp_backup_tasks', $tasks);
2132
- }
2133
-
2134
-
2135
-
2136
- } else {
2137
- $return = array(
2138
- 'error' => 'Backup file not found on your server. Please try again.'
2139
- );
2140
- }
2141
-
2142
- return $return;
2143
-
2144
- }
2145
-
2146
- function validate_task($args, $url)
2147
- {
2148
- if (!class_exists('WP_Http')) {
2149
- include_once(ABSPATH . WPINC . '/class-http.php');
2150
- }
2151
- $params = array();
2152
- $params['body'] = $args;
2153
- $result = wp_remote_post($url, $params);
2154
- if (is_array($result) && $result['body'] == 'mwp_delete_task') {
2155
- //$tasks = $this->get_backup_settings();
2156
- $tasks = $this->tasks;
2157
- unset($tasks[$args['task_name']]);
2158
- $this->update_tasks($tasks);
2159
- $this->cleanup();
2160
- exit;
2161
- } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
2162
- return 'paused';
2163
- }
2164
-
2165
- return 'ok';
2166
- }
2167
-
2168
- function update_status($task_name, $status, $completed = false)
2169
- {
2170
- /* Statuses:
2171
- 0 - Backup started
2172
- 1 - DB dump
2173
- 2 - DB ZIP
2174
- 3 - Files ZIP
2175
- 4 - Amazon S3
2176
- 5 - Dropbox
2177
- 6 - FTP
2178
- 7 - Email
2179
- 100 - Finished
2180
- */
2181
- if ($task_name != 'Backup Now') {
2182
- $tasks = $this->tasks;
2183
- $index = count($tasks[$task_name]['task_results']) - 1;
2184
- if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
2185
- $tasks[$task_name]['task_results'][$index]['status'] = array();
2186
- }
2187
- if (!$completed) {
2188
- $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
2189
- } else {
2190
- $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
2191
- $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
2192
- }
2193
-
2194
- $this->update_tasks($tasks);
2195
- //update_option('mwp_backup_tasks',$tasks);
2196
- }
2197
- }
2198
-
2199
- function update_tasks($tasks)
2200
- {
2201
- $this->tasks = $tasks;
2202
- update_option('mwp_backup_tasks', $tasks);
2203
- }
2204
-
2205
- function wpdb_reconnect(){
2206
- global $wpdb;
2207
- //Reconnect to avoid timeout problem after ZIP files
2208
- if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
2209
- @mysql_close($wpdb->dbh);
2210
- $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2211
- wp_set_wpdb_vars();
2212
- }
2213
- }
2214
-
2215
- function replace_htaccess($url)
2216
- {
2217
- $file = @file_get_contents(ABSPATH.'.htaccess');
2218
- if ($file && strlen($file)) {
2219
- $args = parse_url($url);
2220
- $string = rtrim($args['path'], "/");
2221
- $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
2222
- $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
2223
- $file = preg_replace($regex, $replace, $file);
2224
- @file_put_contents(ABSPATH.'.htaccess', $file);
2225
- }
2226
- }
2227
-
2228
- function check_cron_remove(){
2229
- if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
2230
- wp_clear_scheduled_hook('mwp_backup_tasks');
2231
- exit;
2232
- }
2233
- }
2234
-
2235
- public static function readd_tasks( $params = array() ){
2236
- global $mmb_core;
2237
-
2238
- if( empty($params) || !isset($params['backups']) )
2239
- return $params;
2240
-
2241
- $before = array();
2242
- $tasks = $params['backups'];
2243
- if( !empty($tasks) ){
2244
- $mmb_backup = new MMB_Backup();
2245
-
2246
- if( function_exists( 'wp_next_scheduled' ) ){
2247
- if ( !wp_next_scheduled('mwp_backup_tasks') ) {
2248
- wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
2249
- }
2250
- }
2251
-
2252
- foreach( $tasks as $task ){
2253
- $before[$task['task_name']] = array();
2254
-
2255
- if(isset($task['secure'])){
2256
- if($decrypted = $mmb_core->_secure_data($task['secure'])){
2257
- $decrypted = maybe_unserialize($decrypted);
2258
- if(is_array($decrypted)){
2259
- foreach($decrypted as $key => $val){
2260
- if(!is_numeric($key))
2261
- $task[$key] = $val;
2262
- }
2263
- unset($task['secure']);
2264
- } else
2265
- $task['secure'] = $decrypted;
2266
- }
2267
-
2268
- }
2269
- if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from master first time(secure data)
2270
- $task['args']['account_info'] = $task['account_info'];
2271
- }
2272
-
2273
- $before[$task['task_name']]['task_args'] = $task['args'];
2274
- $before[$task['task_name']]['task_args']['next'] = $mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
2275
- }
2276
- }
2277
- update_option('mwp_backup_tasks', $before);
2278
-
2279
- unset($params['backups']);
2280
- return $params;
2281
- }
2282
- }
2283
-
2284
- if( function_exists('add_filter') ){
2285
- add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
2286
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2287
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * backup.class.php
5
+ *
6
+ * Manage Backups
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "backup.class.php"):
13
+ echo "Sorry but you cannot browse this file directly!";
14
+ exit;
15
+ endif;
16
+ define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
17
+ define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
18
+
19
+ $zip_errors = array(
20
+ 'No error',
21
+ 'No error',
22
+ 'Unexpected end of zip file',
23
+ 'A generic error in the zipfile format was detected.',
24
+ 'zip was unable to allocate itself memory',
25
+ 'A severe error in the zipfile format was detected',
26
+ 'Entry too large to be split with zipsplit',
27
+ 'Invalid comment format',
28
+ 'zip -T failed or out of memory',
29
+ 'The user aborted zip prematurely',
30
+ 'zip encountered an error while using a temp file',
31
+ 'Read or seek error',
32
+ 'zip has nothing to do',
33
+ 'Missing or empty zip file',
34
+ 'Error writing to a file',
35
+ 'zip was unable to create a file to write to',
36
+ 'bad command line parameters',
37
+ 'no error',
38
+ 'zip could not open a specified file to read'
39
+ );
40
+ $unzip_errors = array(
41
+ 'No error',
42
+ 'One or more warning errors were encountered, but processing completed successfully anyway',
43
+ 'A generic error in the zipfile format was detected',
44
+ 'A severe error in the zipfile format was detected.',
45
+ 'unzip was unable to allocate itself memory.',
46
+ 'unzip was unable to allocate memory, or encountered an encryption error',
47
+ 'unzip was unable to allocate memory during decompression to disk',
48
+ 'unzip was unable allocate memory during in-memory decompression',
49
+ 'unused',
50
+ 'The specified zipfiles were not found',
51
+ 'Bad command line parameters',
52
+ 'No matching files were found',
53
+ 50 => 'The disk is (or was) full during extraction',
54
+ 51 => 'The end of the ZIP archive was encountered prematurely.',
55
+ 80 => 'The user aborted unzip prematurely.',
56
+ 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
57
+ 82 => 'No files were found due to bad decryption password(s)'
58
+ );
59
+
60
+
61
+ class MMB_Backup extends MMB_Core
62
+ {
63
+ var $site_name;
64
+ var $statuses;
65
+ var $tasks;
66
+ var $s3;
67
+ var $ftp;
68
+ var $dropbox;
69
+ function __construct()
70
+ {
71
+ parent::__construct();
72
+ $this->site_name = str_replace(array(
73
+ "_",
74
+ "/",
75
+ "~"
76
+ ), array(
77
+ "",
78
+ "-",
79
+ "-"
80
+ ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
81
+ $this->statuses = array(
82
+ 'db_dump' => 1,
83
+ 'db_zip' => 2,
84
+ 'files_zip' => 3,
85
+ 's3' => 4,
86
+ 'dropbox' => 5,
87
+ 'ftp' => 6,
88
+ 'email' => 7,
89
+ 'finished' => 100
90
+ );
91
+ $this->tasks = get_option('mwp_backup_tasks');
92
+ }
93
+
94
+ function set_memory()
95
+ {
96
+ $changed = array('execution_time' => 0, 'memory_limit' => 0);
97
+
98
+ $memory_limit = trim(ini_get('memory_limit'));
99
+ $last = strtolower(substr($memory_limit, -1));
100
+
101
+ if($last == 'g')
102
+ $memory_limit = ((int) $memory_limit)*1024;
103
+ else if($last == 'm')
104
+ $memory_limit = (int) $memory_limit;
105
+ if($last == 'k')
106
+ $memory_limit = ((int) $memory_limit)/1024;
107
+
108
+ if ( $memory_limit < 384 ) {
109
+ @ini_set('memory_limit', '384M');
110
+ $changed['memory_limit'] = 1;
111
+ }
112
+
113
+ if ( (int) @ini_get('max_execution_time') < 600 ) {
114
+ @set_time_limit(600); //ten minutes
115
+ $changed['execution_time'] = 1;
116
+ }
117
+
118
+ return $changed;
119
+
120
+ }
121
+
122
+ function get_backup_settings()
123
+ {
124
+ $backup_settings = get_option('mwp_backup_tasks');
125
+
126
+ if (!empty($backup_settings))
127
+ return $backup_settings;
128
+ else
129
+ return false;
130
+ }
131
+
132
+ function set_backup_task($params)
133
+ {
134
+ //$params => [$task_name, $args, $error]
135
+ if (!empty($params)) {
136
+
137
+ //Make sure backup cron job is set
138
+ if (!wp_next_scheduled('mwp_backup_tasks')) {
139
+ wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
140
+ }
141
+
142
+ extract($params);
143
+
144
+ //$before = $this->get_backup_settings();
145
+ $before = $this->tasks;
146
+ if (!$before || empty($before))
147
+ $before = array();
148
+
149
+ if (isset($args['remove'])) {
150
+ unset($before[$task_name]);
151
+ $return = array(
152
+ 'removed' => true
153
+ );
154
+ } else {
155
+ if (isset($params['account_info']) && is_array($params['account_info'])) { //only if sends from master first time(secure data)
156
+ $args['account_info'] = $account_info;
157
+ }
158
+
159
+ $before[$task_name]['task_args'] = $args;
160
+ if (strlen($args['schedule']))
161
+ $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
162
+
163
+ $return = $before[$task_name];
164
+ }
165
+
166
+ //Update with error
167
+ if (isset($error)) {
168
+ if (is_array($error)) {
169
+ $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
170
+ } else {
171
+ $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
172
+ }
173
+ }
174
+
175
+ if ($time) { //set next result time before backup
176
+ if (is_array($before[$task_name]['task_results'])) {
177
+ $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
178
+ }
179
+ $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
180
+ }
181
+
182
+ $this->update_tasks($before);
183
+ //update_option('mwp_backup_tasks', $before);
184
+
185
+ if ($task_name == 'Backup Now') {
186
+ $result = $this->backup($args, $task_name);
187
+ $backup_settings = $this->tasks;
188
+
189
+ if (is_array($result) && array_key_exists('error', $result)) {
190
+ $return = $result;
191
+ } else {
192
+ $return = $backup_settings[$task_name];
193
+ }
194
+ }
195
+ return $return;
196
+ }
197
+
198
+
199
+
200
+ return false;
201
+ }
202
+
203
+ //Cron check
204
+ function check_backup_tasks()
205
+ {
206
+
207
+ $this->check_cron_remove();
208
+
209
+ $settings = $this->tasks;
210
+ if (is_array($settings) && !empty($settings)) {
211
+ foreach ($settings as $task_name => $setting) {
212
+ if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
213
+ //if ($setting['task_args']['next'] && $_GET['force_backup']) {
214
+ if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
215
+ //Check orphan task
216
+ $check_data = array(
217
+ 'task_name' => $task_name,
218
+ 'task_id' => $setting['task_args']['task_id'],
219
+ 'site_key' => $setting['task_args']['site_key']
220
+ );
221
+
222
+ $check = $this->validate_task($check_data, $setting['task_args']['url']);
223
+
224
+ }
225
+
226
+ $update = array(
227
+ 'task_name' => $task_name,
228
+ 'args' => $settings[$task_name]['task_args']
229
+ );
230
+
231
+
232
+ if($check != 'paused'){
233
+ $update['time'] = time();
234
+ }
235
+
236
+ //Update task with next schedule
237
+ $this->set_backup_task($update);
238
+
239
+ if($check == 'paused'){
240
+ continue;
241
+ }
242
+
243
+
244
+ $result = $this->backup($setting['task_args'], $task_name);
245
+ $error = '';
246
+ if (is_array($result) && array_key_exists('error', $result)) {
247
+ $error = $result;
248
+ $this->set_backup_task(array(
249
+ 'task_name' => $task_name,
250
+ 'args' => $settings[$task_name]['task_args'],
251
+ 'error' => $error
252
+ ));
253
+ } else {
254
+ $error = '';
255
+ }
256
+ break; //Only one backup per cron
257
+ }
258
+ }
259
+ }
260
+
261
+ }
262
+
263
+ function task_now($task_name){
264
+
265
+ $settings = $this->tasks;
266
+ if(!array_key_exists($task_name,$settings)){
267
+ return array('error' => $task_name." does not exist.");
268
+ } else {
269
+ $setting = $settings[$task_name];
270
+ }
271
+
272
+ $this->set_backup_task(array(
273
+ 'task_name' => $task_name,
274
+ 'args' => $settings[$task_name]['task_args'],
275
+ 'time' => time()
276
+ ));
277
+
278
+ //Run backup
279
+ $result = $this->backup($setting['task_args'], $task_name);
280
+
281
+ //Check for error
282
+ if (is_array($result) && array_key_exists('error', $result)) {
283
+ $this->set_backup_task(array(
284
+ 'task_name' => $task_name,
285
+ 'args' => $settings[$task_name]['task_args'],
286
+ 'error' => $result
287
+ ));
288
+ return $result;
289
+ } else {
290
+ return $this->get_backup_stats();
291
+ }
292
+ }
293
+
294
+
295
+
296
+ /*
297
+ * If Task Name not set then it's manual backup
298
+ * Backup args:
299
+ * type -> db, full
300
+ * what -> daily, weekly, monthly
301
+ * account_info -> ftp, amazons3, dropbox
302
+ * exclude-> array of paths to exclude from backup
303
+ */
304
+
305
+ function backup($args, $task_name = false)
306
+ {
307
+
308
+ $this->_log($this->tasks);
309
+
310
+ if (!$args || empty($args))
311
+ return false;
312
+
313
+ extract($args); //extract settings
314
+
315
+ //Try increase memory limit and execution time
316
+ $this->set_memory();
317
+
318
+ //Remove old backup(s)
319
+ $this->remove_old_backups($task_name);
320
+
321
+
322
+
323
+ $new_file_path = MWP_BACKUP_DIR;
324
+
325
+ if (!file_exists($new_file_path)) {
326
+ if (!mkdir($new_file_path, 0755, true))
327
+ return array(
328
+ 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
329
+ );
330
+ }
331
+
332
+ @file_put_contents($new_file_path . '/index.php', ''); //safe
333
+
334
+ //Prepare .zip file name
335
+ $hash = md5(time());
336
+ $label = $type ? $type : 'manual';
337
+ $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
338
+ $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
339
+
340
+ //Optimize tables?
341
+ if (isset($optimize_tables) && !empty($optimize_tables)) {
342
+ $this->optimize_tables();
343
+ }
344
+
345
+ //What to backup - db or full?
346
+ if (trim($what) == 'db') {
347
+ //Take database backup
348
+ $this->update_status($task_name, $this->statuses['db_dump']);
349
+ $db_result = $this->backup_db();
350
+ if ($db_result == false) {
351
+ return array(
352
+ 'error' => 'Failed to backup database.'
353
+ );
354
+ } else if (is_array($db_result) && isset($db_result['error'])) {
355
+ return array(
356
+ 'error' => $db_result['error']
357
+ );
358
+ } else {
359
+ $this->update_status($task_name, $this->statuses['db_dump'], true);
360
+ $this->update_status($task_name, $this->statuses['db_zip']);
361
+
362
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
363
+ $comp_level = $disable_comp ? '-0' : '-1';
364
+
365
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
366
+ chdir(MWP_BACKUP_DIR);
367
+ $zip = $this->get_zip();
368
+ $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
369
+ ob_start();
370
+ $result = $this->mmb_exec($command);
371
+ ob_get_clean();
372
+
373
+ if (!$result) { // fallback to pclzip
374
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
375
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
376
+ $archive = new PclZip($backup_file);
377
+ if ($disable_comp) {
378
+ $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
379
+ } else {
380
+ $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
381
+ }
382
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
383
+ @unlink($db_result);
384
+ @rmdir(MWP_DB_DIR);
385
+
386
+ if (!$result) {
387
+ return array(
388
+ 'error' => 'Failed to zip database (pclZip - ' . $archive->error_code . '): .' . $archive->error_string
389
+ );
390
+ }
391
+ }
392
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
393
+ @unlink($db_result);
394
+ @rmdir(MWP_DB_DIR);
395
+
396
+ if (!$result) {
397
+ return array(
398
+ 'error' => 'Failed to zip database.'
399
+ );
400
+ }
401
+ $this->update_status($task_name, $this->statuses['db_zip'], true);
402
+ }
403
+ } elseif (trim($what) == 'full') {
404
+ $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
405
+ if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
406
+ return array(
407
+ 'error' => $content_backup['error']
408
+ );
409
+ }
410
+ }
411
+
412
+ //Update backup info
413
+ if ($task_name) {
414
+ //backup task (scheduled)
415
+ $backup_settings = $this->tasks;
416
+ $paths = array();
417
+ $size = ceil(filesize($backup_file) / 1024);
418
+
419
+ if ($size > 1000) {
420
+ $paths['size'] = ceil($size / 1024) . "Mb";
421
+ } else {
422
+ $paths['size'] = $size . 'kb';
423
+ }
424
+
425
+ if ($task_name != 'Backup Now') {
426
+ if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
427
+ $paths['server'] = array(
428
+ 'file_path' => $backup_file,
429
+ 'file_url' => $backup_url
430
+ );
431
+ }
432
+ } else {
433
+ $paths['server'] = array(
434
+ 'file_path' => $backup_file,
435
+ 'file_url' => $backup_url
436
+ );
437
+ }
438
+
439
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
440
+ $paths['ftp'] = basename($backup_url);
441
+ }
442
+
443
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
444
+ $paths['amazons3'] = basename($backup_url);
445
+ }
446
+
447
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
448
+ $paths['dropbox'] = basename($backup_url);
449
+ }
450
+
451
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
452
+ $paths['email'] = basename($backup_url);
453
+ }
454
+
455
+ $temp = $backup_settings[$task_name]['task_results'];
456
+ $temp = array_values($temp);
457
+ $paths['time'] = time();
458
+
459
+ if ($task_name != 'Backup Now') {
460
+ $paths['status'] = $temp[count($temp) - 1]['status'];
461
+ $temp[count($temp) - 1] = $paths;
462
+
463
+ } else {
464
+ $temp[count($temp)] = $paths;
465
+ }
466
+
467
+ $backup_settings[$task_name]['task_results'] = $temp;
468
+ $this->update_tasks($backup_settings);
469
+ //update_option('mwp_backup_tasks', $backup_settings);
470
+ }
471
+
472
+
473
+ //Additional: Email, ftp, amazon_s3, dropbox...
474
+
475
+ if ($task_name != 'Backup Now') {
476
+ if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
477
+ $this->update_status($task_name, $this->statuses['ftp']);
478
+ $account_info['mwp_ftp']['backup_file'] = $backup_file;
479
+ $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
480
+
481
+ if ($ftp_result !== true && $del_host_file) {
482
+ @unlink($backup_file);
483
+ }
484
+
485
+ if (is_array($ftp_result) && isset($ftp_result['error'])) {
486
+ return $ftp_result;
487
+ }
488
+ $this->wpdb_reconnect();
489
+ $this->update_status($task_name, $this->statuses['ftp'], true);
490
+ }
491
+
492
+ if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
493
+ $this->update_status($task_name, $this->statuses['s3']);
494
+ $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
495
+ $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
496
+ if ($amazons3_result !== true && $del_host_file) {
497
+ @unlink($backup_file);
498
+ }
499
+ if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
500
+ return $amazons3_result;
501
+ }
502
+ $this->wpdb_reconnect();
503
+ $this->update_status($task_name, $this->statuses['s3'], true);
504
+ }
505
+
506
+ if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
507
+ $this->update_status($task_name, $this->statuses['dropbox']);
508
+ $account_info['mwp_dropbox']['backup_file'] = $backup_file;
509
+ $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
510
+ if ($dropbox_result !== true && $del_host_file) {
511
+ @unlink($backup_file);
512
+ }
513
+
514
+ if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
515
+ return $dropbox_result;
516
+ }
517
+ $this->wpdb_reconnect();
518
+ $this->update_status($task_name, $this->statuses['dropbox'], true);
519
+ }
520
+
521
+ if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
522
+ $this->update_status($task_name, $this->statuses['email']);
523
+ $account_info['mwp_email']['task_name'] = $task_name;
524
+ $account_info['mwp_email']['file_path'] = $backup_file;
525
+
526
+ $email_result = $this->email_backup($account_info['mwp_email']);
527
+ if (is_array($email_result) && isset($email_result['error'])) {
528
+ return $email_result;
529
+ }
530
+ $this->update_status($task_name, $this->statuses['email'], true);
531
+ }
532
+
533
+ if ($del_host_file) {
534
+ @unlink($backup_file);
535
+ }
536
+
537
+ } //end additional
538
+
539
+ //$this->update_status($task_name,$this->statuses['finished'],true);
540
+ return $backup_url; //Return url to backup file
541
+ }
542
+
543
+ function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
544
+ {
545
+ global $zip_errors;
546
+ $sys = substr(PHP_OS, 0, 3);
547
+
548
+ $this->update_status($task_name, $this->statuses['db_dump']);
549
+ $db_result = $this->backup_db();
550
+
551
+ if ($db_result == false) {
552
+ return array(
553
+ 'error' => 'Failed to backup database.'
554
+ );
555
+ } else if (is_array($db_result) && isset($db_result['error'])) {
556
+ return array(
557
+ 'error' => $db_result['error']
558
+ );
559
+ }
560
+
561
+ $this->update_status($task_name, $this->statuses['db_dump'], true);
562
+ $this->update_status($task_name, $this->statuses['db_zip']);
563
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
564
+ $comp_level = $disable_comp ? '-0' : '-1';
565
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
566
+ $zip = $this->get_zip();
567
+ //Add database file
568
+ chdir(MWP_BACKUP_DIR);
569
+ $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
570
+ ob_start();
571
+ $result = $this->mmb_exec($command);
572
+ ob_get_clean();
573
+
574
+
575
+ if (!$result) {
576
+ $this->_log("DB zip fallback to pclZip");
577
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
578
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
579
+ $archive = new PclZip($backup_file);
580
+
581
+ if ($disable_comp) {
582
+ $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
583
+ } else {
584
+ $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
585
+ }
586
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
587
+ @unlink($db_result);
588
+ @rmdir(MWP_DB_DIR);
589
+
590
+ if (!$result_db) {
591
+ return array(
592
+ 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
593
+ );
594
+ }
595
+ }
596
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
597
+ @unlink($db_result);
598
+ @rmdir(MWP_DB_DIR);
599
+
600
+ $this->update_status($task_name, $this->statuses['db_zip'], true);
601
+
602
+
603
+ //Always remove backup folders
604
+ $remove = array(
605
+ trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
606
+ trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
607
+ );
608
+
609
+ //Exclude paths
610
+ $exclude_data = "-x";
611
+
612
+ $exclude_file_data = '';
613
+
614
+ if (!empty($exclude)) {
615
+ foreach ($exclude as $data) {
616
+ if (is_dir(ABSPATH . $data)) {
617
+ if ($sys == 'WIN')
618
+ $exclude_data .= " $data/*.*";
619
+ else
620
+ $exclude_data .= " '$data/*'";
621
+
622
+
623
+ } else {
624
+ if ($sys == 'WIN'){
625
+ if(file_exists(ABSPATH . $data)){
626
+ $exclude_data .= " $data";
627
+ $exclude_file_data .= " $data";
628
+ }
629
+ } else {
630
+ if(file_exists(ABSPATH . $data)){
631
+ $exclude_data .= " '$data'";
632
+ $exclude_file_data .= " '$data'";
633
+ }
634
+ }
635
+ }
636
+ }
637
+ }
638
+
639
+ if($exclude_file_data){
640
+ $exclude_file_data = "-x".$exclude_file_data;
641
+ }
642
+
643
+ foreach ($remove as $data) {
644
+ if ($sys == 'WIN')
645
+ $exclude_data .= " $data/*.*";
646
+ else
647
+ $exclude_data .= " '$data/*'";
648
+ }
649
+
650
+ //Include paths by default
651
+ $add = array(
652
+ trim(WPINC),
653
+ trim(basename(WP_CONTENT_DIR)),
654
+ "wp-admin"
655
+ );
656
+
657
+ $include_data = ". -i";
658
+ foreach ($add as $data) {
659
+ if ($sys == 'WIN')
660
+ $include_data .= " $data/*.*";
661
+ else
662
+ $include_data .= " '$data/*'";
663
+ }
664
+
665
+ //Additional includes?
666
+ if (!empty($include)) {
667
+ foreach ($include as $data) {
668
+ if ($data) {
669
+ if ($sys == 'WIN')
670
+ $include_data .= " $data/*.*";
671
+ else
672
+ $include_data .= " '$data/*'";
673
+ }
674
+ }
675
+ }
676
+
677
+ $this->update_status($task_name, $this->statuses['files_zip']);
678
+ chdir(ABSPATH);
679
+ ob_start();
680
+ $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
681
+ $result_f = $this->mmb_exec($command, false, true);
682
+ if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
683
+ $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
684
+ $result_d = $this->mmb_exec($command, false, true);
685
+ if ($result_d && $result_d != 18) {
686
+ @unlink($backup_file);
687
+ if ($result_d > 0 && $result_d < 18)
688
+ return array(
689
+ 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
690
+ );
691
+ else
692
+ return array(
693
+ 'error' => 'Failed to archive files.'
694
+ );
695
+ }
696
+ }
697
+ ob_get_clean();
698
+
699
+ if ($result_f && $result_f != 18) { //Try pclZip
700
+ $this->_log("Files zip fallback to pclZip");
701
+ if (!isset($archive)) {
702
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
703
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
704
+ $archive = new PclZip($backup_file);
705
+ }
706
+
707
+ //Include paths
708
+ $include_data = array();
709
+ if (!empty($include)) {
710
+ foreach ($include as $data) {
711
+ if ($data && file_exists(ABSPATH . $data))
712
+ $include_data[] = ABSPATH . $data . '/';
713
+ }
714
+ }
715
+
716
+ foreach ($add as $data) {
717
+ if (file_exists(ABSPATH . $data))
718
+ $include_data[] = ABSPATH . $data . '/';
719
+ }
720
+
721
+ //Include root files
722
+ if ($handle = opendir(ABSPATH)) {
723
+ while (false !== ($file = readdir($handle))) {
724
+ if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
725
+ $include_data[] = ABSPATH . $file;
726
+ }
727
+ }
728
+ closedir($handle);
729
+ }
730
+
731
+ if ($disable_comp) {
732
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION);
733
+ } else {
734
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH);
735
+ }
736
+ if (!$result) {
737
+ @unlink($backup_file);
738
+ return array(
739
+ 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
740
+ );
741
+ }
742
+
743
+ //Now exclude paths
744
+ $exclude_data = array();
745
+ if (!empty($exclude)) {
746
+ foreach ($exclude as $data) {
747
+ if (is_dir(ABSPATH . $data))
748
+ $exclude_data[] = $data . '/';
749
+ else
750
+ $exclude_data[] = $data;
751
+ }
752
+ }
753
+
754
+ foreach ($remove as $rem) {
755
+ $exclude_data[] = $rem . '/';
756
+ }
757
+
758
+ $result_excl = $archive->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
759
+ if (!$result_excl) {
760
+ @unlink($backup_file);
761
+ return array(
762
+ 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
763
+ );
764
+ }
765
+
766
+ }
767
+
768
+ //Reconnect
769
+ $this->wpdb_reconnect();
770
+
771
+ $this->update_status($task_name, $this->statuses['files_zip'], true);
772
+ return true;
773
+ }
774
+
775
+
776
+ function backup_db()
777
+ {
778
+ $db_folder = MWP_DB_DIR . '/';
779
+ if (!file_exists($db_folder)) {
780
+ if (!mkdir($db_folder, 0755, true))
781
+ return array(
782
+ 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
783
+ );
784
+ }
785
+
786
+ $file = $db_folder . DB_NAME . '.sql';
787
+ $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
788
+ return $result;
789
+ }
790
+
791
+ function backup_db_dump($file)
792
+ {
793
+ global $wpdb;
794
+ $paths = $this->check_mysql_paths();
795
+ $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
796
+ $command = $brace . $paths['mysqldump'] . $brace . ' --force --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --add-drop-table --skip-lock-tables "' . DB_NAME . '" > ' . $brace . $file . $brace;
797
+ ob_start();
798
+ $result = $this->mmb_exec($command);
799
+ ob_get_clean();
800
+
801
+ if (!$result) { // Fallback to php
802
+ $this->_log("DB dump fallback to php");
803
+ $result = $this->backup_db_php($file);
804
+ return $result;
805
+ }
806
+
807
+ if (filesize($file) == 0 || !is_file($file) || !$result) {
808
+ @unlink($file);
809
+ return false;
810
+ } else {
811
+ return $file;
812
+ }
813
+ }
814
+
815
+ function backup_db_php($file)
816
+ {
817
+ global $wpdb;
818
+ $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
819
+ foreach ($tables as $table) {
820
+ //drop existing table
821
+ $dump_data = "DROP TABLE IF EXISTS $table[0];";
822
+ //create table
823
+ $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
824
+ $dump_data .= "\n\n" . $create_table[1] . ";\n\n";
825
+
826
+ $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
827
+ if ($count > 100)
828
+ $count = ceil($count / 100);
829
+ else if ($count > 0)
830
+ $count = 1;
831
+
832
+ for ($i = 0; $i < $count; $i++) {
833
+ $low_limit = $i * 100;
834
+ $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
835
+ $rows = $wpdb->get_results($qry, ARRAY_A);
836
+ if (is_array($rows)) {
837
+ foreach ($rows as $row) {
838
+ //insert single row
839
+ $dump_data .= "INSERT INTO $table[0] VALUES(";
840
+ $num_values = count($row);
841
+ $j = 1;
842
+ foreach ($row as $value) {
843
+ $value = addslashes($value);
844
+ $value = preg_replace("/\n/Ui", "\\n", $value);
845
+ $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
846
+ $j++;
847
+ unset($value);
848
+ }
849
+ $dump_data .= ");\n";
850
+ }
851
+ }
852
+ }
853
+ $dump_data .= "\n\n\n";
854
+
855
+ unset($rows);
856
+ file_put_contents($file, $dump_data, FILE_APPEND);
857
+ unset($dump_data);
858
+ }
859
+
860
+ if (filesize($file) == 0 || !is_file($file)) {
861
+ @unlink($file);
862
+ return array(
863
+ 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
864
+ );
865
+ }
866
+
867
+ return $file;
868
+
869
+ }
870
+
871
+ function restore($args)
872
+ {
873
+ $this->_log($args);
874
+ global $wpdb;
875
+ if (empty($args)) {
876
+ return false;
877
+ }
878
+
879
+ extract($args);
880
+ $this->set_memory();
881
+
882
+ $unlink_file = true; //Delete file after restore
883
+
884
+ //Detect source
885
+ if ($backup_url) {
886
+ //This is for clone (overwrite)
887
+ include_once ABSPATH . 'wp-admin/includes/file.php';
888
+ $backup_file = download_url($backup_url);
889
+ if (is_wp_error($backup_file)) {
890
+ return array(
891
+ 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
892
+ );
893
+ }
894
+ $what = 'full';
895
+ } else {
896
+ $tasks = $this->tasks;
897
+ $task = $tasks[$task_name];
898
+ if (isset($task['task_results'][$result_id]['server'])) {
899
+ $backup_file = $task['task_results'][$result_id]['server']['file_path'];
900
+ $unlink_file = false; //Don't delete file if stored on server
901
+ } elseif (isset($task['task_results'][$result_id]['ftp'])) {
902
+ $ftp_file = $task['task_results'][$result_id]['ftp'];
903
+ $args = $task['task_args']['account_info']['mwp_ftp'];
904
+ $args['backup_file'] = $ftp_file;
905
+ $backup_file = $this->get_ftp_backup($args);
906
+ if ($backup_file == false) {
907
+ return array(
908
+ 'error' => 'Failed to download file from FTP.'
909
+ );
910
+ }
911
+ } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
912
+ $amazons3_file = $task['task_results'][$result_id]['amazons3'];
913
+ $args = $task['task_args']['account_info']['mwp_amazon_s3'];
914
+ $args['backup_file'] = $amazons3_file;
915
+ $backup_file = $this->get_amazons3_backup($args);
916
+ if ($backup_file == false) {
917
+ return array(
918
+ 'error' => 'Failed to download file from Amazon S3.'
919
+ );
920
+ }
921
+ } elseif(isset($task['task_results'][$result_id]['dropbox'])){
922
+ $dropbox_file = $task['task_results'][$result_id]['dropbox'];
923
+ $args = $task['task_args']['account_info']['mwp_dropbox'];
924
+ $args['backup_file'] = $dropbox_file;
925
+ $backup_file = $this->get_dropbox_backup($args);
926
+
927
+ if ($backup_file == false) {
928
+ return array(
929
+ 'error' => 'Failed to download file from Dropbox.'
930
+ );
931
+ }
932
+ }
933
+
934
+ $what = $tasks[$task_name]['task_args']['what'];
935
+ }
936
+
937
+ $this->wpdb_reconnect();
938
+
939
+ if ($backup_file && file_exists($backup_file)) {
940
+ if ($overwrite) {
941
+ //Keep old db credentials before overwrite
942
+ if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
943
+ @unlink($backup_file);
944
+ return array(
945
+ 'error' => 'Error creating wp-config. Please check your write permissions.'
946
+ );
947
+ }
948
+
949
+ $db_host = DB_HOST;
950
+ $db_user = DB_USER;
951
+ $db_password = DB_PASSWORD;
952
+ $home = rtrim(get_option('home'), "/");
953
+ $site_url = get_option('site_url');
954
+
955
+ $clone_options = array();
956
+ if (trim($clone_from_url) || trim($mwp_clone)) {
957
+
958
+ $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
959
+ $clone_options['_worker_public_key'] = get_option('_worker_public_key');
960
+ $clone_options['_action_message_id'] = get_option('_action_message_id');
961
+
962
+ }
963
+ $clone_options['upload_path'] = get_option('upload_path');
964
+ $clone_options['upload_url_path'] = get_option('upload_url_path');
965
+
966
+ $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
967
+ $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
968
+ $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
969
+
970
+
971
+ } else {
972
+ $restore_options = array();
973
+ $restore_options['mwp_notifications'] = get_option('mwp_notifications');
974
+ $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
975
+ $restore_options['user_hit_count'] = get_option('user_hit_count');
976
+ }
977
+
978
+
979
+ chdir(ABSPATH);
980
+ $unzip = $this->get_unzip();
981
+ $command = "$unzip -o $backup_file";
982
+ ob_start();
983
+ $result = $this->mmb_exec($command);
984
+ ob_get_clean();
985
+
986
+ if (!$result) { //fallback to pclzip
987
+ $this->_log("Files uznip fallback to pclZip");
988
+ define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
989
+ require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
990
+ $archive = new PclZip($backup_file);
991
+ $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
992
+ }
993
+
994
+ if ($unlink_file) {
995
+ @unlink($backup_file);
996
+ }
997
+
998
+ if (!$result) {
999
+ return array(
1000
+ 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
1001
+ );
1002
+ }
1003
+
1004
+ $db_result = $this->restore_db();
1005
+
1006
+ if (!$db_result) {
1007
+ return array(
1008
+ 'error' => 'Error restoring database.'
1009
+ );
1010
+ } else if(is_array($db_result) && isset($db_result['error'])){
1011
+ return array(
1012
+ 'error' => $db_result['error']
1013
+ );
1014
+ }
1015
+
1016
+ } else {
1017
+ return array(
1018
+ 'error' => 'Error restoring. Cannot find backup file.'
1019
+ );
1020
+ }
1021
+
1022
+ $this->wpdb_reconnect();
1023
+
1024
+ //Replace options and content urls
1025
+ if ($overwrite) {
1026
+ //Get New Table prefix
1027
+ $new_table_prefix = trim($this->get_table_prefix());
1028
+ //Retrieve old wp_config
1029
+ @unlink(ABSPATH . 'wp-config.php');
1030
+ //Replace table prefix
1031
+ $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
1032
+
1033
+ foreach ($lines as $line) {
1034
+ if (strstr($line, '$table_prefix')) {
1035
+ $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
1036
+ }
1037
+ file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
1038
+ }
1039
+
1040
+ @unlink(ABSPATH . 'mwp-temp-wp-config.php');
1041
+
1042
+ //Replace options
1043
+ $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
1044
+ $old = $wpdb->get_var($wpdb->prepare($query));
1045
+ $old = rtrim($old, "/");
1046
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'home'";
1047
+ $wpdb->query($wpdb->prepare($query));
1048
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'siteurl'";
1049
+ $wpdb->query($wpdb->prepare($query));
1050
+ //Replace content urls
1051
+ $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, '$old','$home') WHERE post_content REGEXP 'src=\"(.*)$old(.*)\"' OR post_content REGEXP 'href=\"(.*)$old(.*)\"'";
1052
+ $wpdb->query($wpdb->prepare($query));
1053
+
1054
+ if (trim($new_password)) {
1055
+ $new_password = wp_hash_password($new_password);
1056
+ }
1057
+ if (!trim($clone_from_url) && !trim($mwp_clone)) {
1058
+ if ($new_user && $new_password) {
1059
+ $query = "UPDATE " . $new_table_prefix . "users SET user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$old_user'";
1060
+ $wpdb->query($wpdb->prepare($query));
1061
+ }
1062
+ } else {
1063
+ if ($clone_from_url) {
1064
+ if ($new_user && $new_password) {
1065
+ $query = "UPDATE " . $new_table_prefix . "users SET user_pass = '$new_password' WHERE user_login = '$new_user'";
1066
+ $wpdb->query($wpdb->prepare($query));
1067
+ }
1068
+ }
1069
+
1070
+ if ($mwp_clone) {
1071
+ if ($admin_email) {
1072
+ //Clean Install
1073
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$admin_email' WHERE option_name = 'admin_email'";
1074
+ $wpdb->query($wpdb->prepare($query));
1075
+ $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
1076
+ $temp_user = $wpdb->get_row($query);
1077
+ if (!empty($temp_user)) {
1078
+ $query = "UPDATE " . $new_table_prefix . "users SET user_email='$admin_email', user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$temp_user->user_login'";
1079
+ $wpdb->query($wpdb->prepare($query));
1080
+ }
1081
+
1082
+ }
1083
+ }
1084
+ }
1085
+
1086
+ if (is_array($clone_options) && !empty($clone_options)) {
1087
+ foreach ($clone_options as $key => $option) {
1088
+ if (!empty($key)) {
1089
+ $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = '$key'";
1090
+ $res = $wpdb->get_var($query);
1091
+ if ($res == false) {
1092
+ $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES('$option','$key')";
1093
+ $wpdb->query($wpdb->prepare($query));
1094
+ } else {
1095
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$option' WHERE option_name = '$key'";
1096
+ $wpdb->query($wpdb->prepare($query));
1097
+ }
1098
+ }
1099
+ }
1100
+ }
1101
+
1102
+ //Remove hit count
1103
+ $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'user_hit_count'";
1104
+ $wpdb->query($wpdb->prepare($query));
1105
+
1106
+ //Check for .htaccess permalinks update
1107
+ $this->replace_htaccess($home);
1108
+ } else {
1109
+
1110
+ //restore worker options
1111
+ if (is_array($restore_options) && !empty($restore_options)) {
1112
+ foreach ($restore_options as $key => $option) {
1113
+ update_option($key,$option);
1114
+ }
1115
+ }
1116
+
1117
+ }
1118
+
1119
+
1120
+
1121
+
1122
+ return true;
1123
+ }
1124
+
1125
+ function restore_db()
1126
+ {
1127
+ global $wpdb;
1128
+ $paths = $this->check_mysql_paths();
1129
+ $file_path = ABSPATH . 'mwp_db';
1130
+ @chmod($file_path,0755);
1131
+ $file_name = glob($file_path . '/*.sql');
1132
+ $file_name = $file_name[0];
1133
+
1134
+ if(!$file_name){
1135
+ return array('error' => 'Cannot access database file.');
1136
+ }
1137
+
1138
+ $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1139
+ $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
1140
+
1141
+ ob_start();
1142
+ $result = $this->mmb_exec($command);
1143
+ ob_get_clean();
1144
+ if (!$result) {
1145
+ $this->_log('DB restore fallback to PHP');
1146
+ //try php
1147
+ $this->restore_db_php($file_name);
1148
+ }
1149
+
1150
+
1151
+ @unlink($file_name);
1152
+ return true;
1153
+ }
1154
+
1155
+ function restore_db_php($file_name)
1156
+ {
1157
+ global $wpdb;
1158
+ $current_query = '';
1159
+ // Read in entire file
1160
+ $lines = file($file_name);
1161
+ // Loop through each line
1162
+ foreach ($lines as $line) {
1163
+ // Skip it if it's a comment
1164
+ if (substr($line, 0, 2) == '--' || $line == '')
1165
+ continue;
1166
+
1167
+ // Add this line to the current query
1168
+ $current_query .= $line;
1169
+ // If it has a semicolon at the end, it's the end of the query
1170
+ if (substr(trim($line), -1, 1) == ';') {
1171
+ // Perform the query
1172
+ $result = $wpdb->query($current_query);
1173
+ if ($result === false)
1174
+ return false;
1175
+ // Reset temp variable to empty
1176
+ $current_query = '';
1177
+ }
1178
+ }
1179
+
1180
+ @unlink($file_name);
1181
+ return true;
1182
+ }
1183
+
1184
+ function get_table_prefix()
1185
+ {
1186
+ $lines = file(ABSPATH . 'wp-config.php');
1187
+ foreach ($lines as $line) {
1188
+ if (strstr($line, '$table_prefix')) {
1189
+ $pattern = "/(\'|\")[^(\'|\")]*/";
1190
+ preg_match($pattern, $line, $matches);
1191
+ $prefix = substr($matches[0], 1);
1192
+ return $prefix;
1193
+ break;
1194
+ }
1195
+ }
1196
+ return 'wp_'; //default
1197
+ }
1198
+
1199
+ function optimize_tables()
1200
+ {
1201
+ global $wpdb;
1202
+ $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
1203
+ $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1204
+ foreach ($tables as $table) {
1205
+ if (in_array($table['Engine'], array(
1206
+ 'MyISAM',
1207
+ 'ISAM',
1208
+ 'HEAP',
1209
+ 'MEMORY',
1210
+ 'ARCHIVE'
1211
+ )))
1212
+ $table_string .= $table['Name'] . ",";
1213
+ elseif ($table['Engine'] == 'InnoDB') {
1214
+ $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1215
+ }
1216
+ }
1217
+
1218
+ $table_string = rtrim($table_string);
1219
+ $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1220
+
1221
+ return $optimize ? true : false;
1222
+ }
1223
+
1224
+ ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1225
+ function check_mysql_paths()
1226
+ {
1227
+ global $wpdb;
1228
+ $paths = array(
1229
+ 'mysql' => '',
1230
+ 'mysqldump' => ''
1231
+ );
1232
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
1233
+ $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1234
+ if ($mysql_install) {
1235
+ $install_path = str_replace('\\', '/', $mysql_install->Value);
1236
+ $paths['mysql'] = $install_path . 'bin/mysql.exe';
1237
+ $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1238
+ } else {
1239
+ $paths['mysql'] = 'mysql.exe';
1240
+ $paths['mysqldump'] = 'mysqldump.exe';
1241
+ }
1242
+ } else {
1243
+ $paths['mysql'] = $this->mmb_exec('which mysql', true);
1244
+ if (empty($paths['mysql']))
1245
+ $paths['mysql'] = 'mysql'; // try anyway
1246
+
1247
+ $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1248
+ if (empty($paths['mysqldump']))
1249
+ $paths['mysqldump'] = 'mysqldump'; // try anyway
1250
+
1251
+ }
1252
+
1253
+
1254
+ return $paths;
1255
+ }
1256
+
1257
+ //Check if exec, system, passthru functions exist
1258
+ function check_sys()
1259
+ {
1260
+ if ($this->mmb_function_exists('exec'))
1261
+ return 'exec';
1262
+
1263
+ if ($this->mmb_function_exists('system'))
1264
+ return 'system';
1265
+
1266
+ if ($this->mmb_function_exists('passhtru'))
1267
+ return 'passthru';
1268
+
1269
+ return false;
1270
+
1271
+ }
1272
+
1273
+ function mmb_exec($command, $string = false, $rawreturn = false)
1274
+ {
1275
+ if ($command == '')
1276
+ return false;
1277
+
1278
+ if ($this->mmb_function_exists('exec')) {
1279
+ $log = @exec($command, $output, $return);
1280
+ $this->_log("Type: exec");
1281
+ $this->_log("Command: ".$command);
1282
+ $this->_log("Return: ".$return);
1283
+ if ($string)
1284
+ return $log;
1285
+ if ($rawreturn)
1286
+ return $return;
1287
+
1288
+ return $return ? false : true;
1289
+ } elseif ($this->mmb_function_exists('system')) {
1290
+ $log = @system($command, $return);
1291
+ $this->_log("Type: system");
1292
+ $this->_log("Command: ".$command);
1293
+ $this->_log("Return: ".$return);
1294
+ if ($string)
1295
+ return $log;
1296
+
1297
+ if ($rawreturn)
1298
+ return $return;
1299
+
1300
+ return $return ? false : true;
1301
+ } elseif ($this->mmb_function_exists('passthru') && !$string) {
1302
+ $log = passthru($command, $return);
1303
+ $this->_log("Type: passthru");
1304
+ $this->_log("Command: ".$command);
1305
+ $this->_log("Return: ".$return);
1306
+ if ($rawreturn)
1307
+ return $return;
1308
+
1309
+ return $return ? false : true;
1310
+ }
1311
+
1312
+ if ($rawreturn)
1313
+ return -1;
1314
+
1315
+ return false;
1316
+ }
1317
+
1318
+ function get_zip()
1319
+ {
1320
+ $zip = $this->mmb_exec('which zip', true);
1321
+ if (!$zip)
1322
+ $zip = "zip";
1323
+ return $zip;
1324
+ }
1325
+
1326
+ function get_unzip()
1327
+ {
1328
+ $unzip = $this->mmb_exec('which unzip', true);
1329
+ if (!$unzip)
1330
+ $unzip = "unzip";
1331
+ return $unzip;
1332
+ }
1333
+
1334
+ function check_backup_compat()
1335
+ {
1336
+
1337
+ $reqs = array();
1338
+ if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1339
+ $reqs['Server OS']['status'] = 'Linux (or compatible)';
1340
+ $reqs['Server OS']['pass'] = true;
1341
+ } else {
1342
+ $reqs['Server OS']['status'] = 'Windows';
1343
+ $reqs['Server OS']['pass'] = true;
1344
+ $pass = false;
1345
+ }
1346
+ $reqs['PHP Version']['status'] = phpversion();
1347
+ if ((float) phpversion() >= 5.1) {
1348
+ $reqs['PHP Version']['pass'] = true;
1349
+ } else {
1350
+ $reqs['PHP Version']['pass'] = false;
1351
+ $pass = false;
1352
+ }
1353
+
1354
+
1355
+ if (is_writable(WP_CONTENT_DIR)) {
1356
+ $reqs['Backup Folder']['status'] = "writable";
1357
+ $reqs['Backup Folder']['pass'] = true;
1358
+ } else {
1359
+ $reqs['Backup Folder']['status'] = "not writable";
1360
+ $reqs['Backup Folder']['pass'] = false;
1361
+ }
1362
+
1363
+
1364
+ $file_path = MWP_BACKUP_DIR;
1365
+ $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1366
+
1367
+ if ($func = $this->check_sys()) {
1368
+ $reqs['Execute Function']['status'] = $func;
1369
+ $reqs['Execute Function']['pass'] = true;
1370
+ } else {
1371
+ $reqs['Execute Function']['status'] = "not found";
1372
+ $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1373
+ $reqs['Execute Function']['pass'] = false;
1374
+ }
1375
+ $reqs['Zip']['status'] = $this->get_zip();
1376
+
1377
+ $reqs['Zip']['pass'] = true;
1378
+
1379
+
1380
+
1381
+ $reqs['Unzip']['status'] = $this->get_unzip();
1382
+
1383
+ $reqs['Unzip']['pass'] = true;
1384
+
1385
+ $paths = $this->check_mysql_paths();
1386
+
1387
+ if (!empty($paths['mysqldump'])) {
1388
+ $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1389
+ $reqs['MySQL Dump']['pass'] = true;
1390
+ } else {
1391
+ $reqs['MySQL Dump']['status'] = "not found";
1392
+ $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1393
+ $reqs['MySQL Dump']['pass'] = false;
1394
+ }
1395
+
1396
+ $exec_time = ini_get('max_execution_time');
1397
+ $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1398
+ $reqs['Execution time']['pass'] = true;
1399
+
1400
+ $mem_limit = ini_get('memory_limit');
1401
+ $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1402
+ $reqs['Memory limit']['pass'] = true;
1403
+
1404
+ $changed = $this->set_memory();
1405
+ if($changed['execution_time']){
1406
+ $exec_time = ini_get('max_execution_time');
1407
+ $reqs['Execution time']['status'] .= $exec_time ? ' (will try '.$exec_time . 's)' : ' (unknown)';
1408
+ }
1409
+ if($changed['memory_limit']){
1410
+ $mem_limit = ini_get('memory_limit');
1411
+ $reqs['Memory limit']['status'] .= $mem_limit ? ' (will try '.$mem_limit.')' : ' (unknown)';
1412
+ }
1413
+
1414
+ if(defined('MWP_SHOW_LOG') && MWP_SHOW_LOG == true){
1415
+ $md5 = get_option('mwp_log_md5');
1416
+ if ($md5 !== false) {
1417
+ global $mmb_plugin_url;
1418
+ $md5 = "<a href='$mmb_plugin_url/log_$md5' target='_blank'>$md5</a>";
1419
+ } else {
1420
+ $md5 = "not created";
1421
+ }
1422
+ $reqs['Backup Log']['status'] = $md5;
1423
+ $reqs['Backup Log']['pass'] = true;
1424
+ }
1425
+
1426
+ return $reqs;
1427
+ }
1428
+
1429
+ function email_backup($args)
1430
+ {
1431
+ $email = $args['email'];
1432
+
1433
+ if (!is_email($email)) {
1434
+ return array(
1435
+ 'error' => 'Your email (' . $email . ') is not correct'
1436
+ );
1437
+ }
1438
+ $backup_file = $args['file_path'];
1439
+ $task_name = isset($args['task_name']) ? $args['task_name'] : '';
1440
+ if (file_exists($backup_file) && $email) {
1441
+ $attachments = array(
1442
+ $backup_file
1443
+ );
1444
+ $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
1445
+ $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
1446
+ ob_start();
1447
+ $result = wp_mail($email, $subject, $subject, $headers, $attachments);
1448
+ ob_end_clean();
1449
+
1450
+ }
1451
+
1452
+ if (!$result) {
1453
+ return array(
1454
+ 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
1455
+ );
1456
+ }
1457
+ return true;
1458
+
1459
+ }
1460
+
1461
+ function ftp_backup($args)
1462
+ {
1463
+ extract($args);
1464
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1465
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
1466
+ if ($ftp_ssl) {
1467
+ if (function_exists('ftp_ssl_connect')) {
1468
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1469
+ } else {
1470
+ return array(
1471
+ 'error' => 'FTPS disabled: Please enable ftp_ssl_connect in PHP',
1472
+ 'partial' => 1
1473
+ );
1474
+ }
1475
+ } else {
1476
+ if (function_exists('ftp_connect')) {
1477
+ $conn_id = ftp_connect($ftp_hostname,$port);
1478
+ if ($conn_id === false) {
1479
+ return array(
1480
+ 'error' => 'Failed to connect to ' . $ftp_hostname,
1481
+ 'partial' => 1
1482
+ );
1483
+ }
1484
+ } else {
1485
+ return array(
1486
+ 'error' => 'FTP disabled: Please enable ftp_connect in PHP',
1487
+ 'partial' => 1
1488
+ );
1489
+ }
1490
+ }
1491
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1492
+ if ($login === false) {
1493
+ return array(
1494
+ 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1495
+ 'partial' => 1
1496
+ );
1497
+ }
1498
+
1499
+ if($ftp_passive){
1500
+ @ftp_pasv($conn_id,true);
1501
+ }
1502
+
1503
+ @ftp_mkdir($conn_id, $ftp_remote_folder);
1504
+ if ($ftp_site_folder) {
1505
+ $ftp_remote_folder .= '/' . $this->site_name;
1506
+ }
1507
+ @ftp_mkdir($conn_id, $ftp_remote_folder);
1508
+
1509
+ $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1510
+ if ($upload === false) { //Try ascii
1511
+ $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1512
+ }
1513
+ ftp_close($conn_id);
1514
+
1515
+ if ($upload === false) {
1516
+ return array(
1517
+ 'error' => 'Failed to upload file to FTP. Please check your specified path.',
1518
+ 'partial' => 1
1519
+ );
1520
+ }
1521
+
1522
+ return true;
1523
+ }
1524
+
1525
+ function remove_ftp_backup($args)
1526
+ {
1527
+ extract($args);
1528
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1529
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
1530
+ if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1531
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1532
+ } else if (function_exists('ftp_connect')) {
1533
+ $conn_id = ftp_connect($ftp_hostname,$port);
1534
+ }
1535
+
1536
+ if ($conn_id) {
1537
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1538
+ if ($ftp_site_folder)
1539
+ $ftp_remote_folder .= '/' . $this->site_name;
1540
+
1541
+ if($ftp_passive){
1542
+ @ftp_pasv($conn_id,true);
1543
+ }
1544
+
1545
+ $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1546
+
1547
+ ftp_close($conn_id);
1548
+ }
1549
+
1550
+ }
1551
+
1552
+ function get_ftp_backup($args)
1553
+ {
1554
+ extract($args);
1555
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1556
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
1557
+ if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1558
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1559
+
1560
+ } else if (function_exists('ftp_connect')) {
1561
+ $conn_id = ftp_connect($ftp_hostname,$port);
1562
+ if ($conn_id === false) {
1563
+ return false;
1564
+ }
1565
+ }
1566
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1567
+ if ($login === false) {
1568
+ return false;
1569
+ } else {
1570
+ }
1571
+
1572
+ if ($ftp_site_folder)
1573
+ $ftp_remote_folder .= '/' . $this->site_name;
1574
+
1575
+ if($ftp_passive){
1576
+ @ftp_pasv($conn_id,true);
1577
+ }
1578
+
1579
+ $temp = ABSPATH . 'mwp_temp_backup.zip';
1580
+ $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1581
+ if ($get === false) {
1582
+ return false;
1583
+ } else {
1584
+ }
1585
+ ftp_close($conn_id);
1586
+
1587
+ return $temp;
1588
+ }
1589
+
1590
+ function dropbox_backup($args)
1591
+ {
1592
+
1593
+ extract($args);
1594
+
1595
+ if(isset($consumer_secret) && !empty($consumer_secret)){
1596
+ //New way
1597
+ require_once('lib/dropbox.oauth.php');
1598
+
1599
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
1600
+ $dropbox->setOAuthToken($oauth_token);
1601
+ $dropbox->setOAuthTokenSecret($oauth_token_secret);
1602
+
1603
+ if ($dropbox_site_folder == true)
1604
+ $dropbox_destination .= '/' . $this->site_name;
1605
+
1606
+ try{
1607
+
1608
+ $dropbox->filesPost($dropbox_destination, $backup_file,true);
1609
+
1610
+ } catch(Exception $e){
1611
+ return array(
1612
+ 'error' => 'Dropbox upload error. '.$e->getMessage()
1613
+ );
1614
+ }
1615
+
1616
+ return true;
1617
+
1618
+ } else {
1619
+ //old way
1620
+ require_once('lib/dropbox.php');
1621
+
1622
+ //$email, $password, $backup_file, $destination, $dropbox_site_folder
1623
+
1624
+ $size = ceil(filesize($backup_file) / 1024);
1625
+ if ($size > 300000) {
1626
+ return array(
1627
+ 'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
1628
+ 'partial' => 1
1629
+ );
1630
+ }
1631
+
1632
+ if ($dropbox_site_folder == true)
1633
+ $dropbox_destination .= '/' . $this->site_name;
1634
+
1635
+ try {
1636
+ $uploader = new DropboxUploader($dropbox_username, $dropbox_password);
1637
+ $uploader->upload($backup_file, $dropbox_destination);
1638
+ }
1639
+ catch (Exception $e) {
1640
+ return array(
1641
+ 'error' => $e->getMessage(),
1642
+ 'partial' => 1
1643
+ );
1644
+ }
1645
+
1646
+ return true;
1647
+ }
1648
+
1649
+ }
1650
+
1651
+ function remove_dropbox_backup($args){
1652
+ extract($args);
1653
+ if(isset($consumer_secret) && !empty($consumer_secret)){
1654
+ //New way
1655
+ require_once('lib/dropbox.oauth.php');
1656
+
1657
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
1658
+ $dropbox->setOAuthToken($oauth_token);
1659
+ $dropbox->setOAuthTokenSecret($oauth_token_secret);
1660
+
1661
+ if ($dropbox_site_folder == true)
1662
+ $dropbox_destination .= '/' . $this->site_name;
1663
+
1664
+ try{
1665
+ $dropbox->fileopsDelete($dropbox_destination.'/'.$backup_file, true);
1666
+ } catch(Exception $e){
1667
+
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ function get_dropbox_backup($args){
1673
+ extract($args);
1674
+
1675
+ if(isset($consumer_secret) && !empty($consumer_secret)){
1676
+ //New way
1677
+ require_once('lib/dropbox.oauth.php');
1678
+
1679
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
1680
+ $dropbox->setOAuthToken($oauth_token);
1681
+ $dropbox->setOAuthTokenSecret($oauth_token_secret);
1682
+
1683
+ if ($dropbox_site_folder == true)
1684
+ $dropbox_destination .= '/' . $this->site_name;
1685
+
1686
+ $temp = ABSPATH . 'mwp_temp_backup.zip';
1687
+
1688
+ try{
1689
+ $file = $dropbox->filesGet($dropbox_destination.'/'.$backup_file, true);
1690
+
1691
+ if(isset($file['data']) && !empty($file['data']) )
1692
+ $stream = base64_decode($file['data']);
1693
+ else
1694
+ return false;
1695
+
1696
+ $handle = @fopen($temp, 'w+');
1697
+ $result = fwrite($handle,$stream);
1698
+ fclose($handle);
1699
+
1700
+ if($result)
1701
+ return $temp;
1702
+ else
1703
+ return false;
1704
+
1705
+ } catch(Exception $e){
1706
+
1707
+
1708
+ return false;
1709
+ }
1710
+
1711
+ } else {
1712
+ return false;
1713
+ }
1714
+
1715
+
1716
+ }
1717
+
1718
+ function amazons3_backup($args)
1719
+ {
1720
+ if ($this->mmb_function_exists('curl_init')) {
1721
+ require_once('lib/s3.php');
1722
+ extract($args);
1723
+
1724
+ if ($as3_site_folder == true)
1725
+ $as3_directory .= '/' . $this->site_name;
1726
+
1727
+ $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1728
+ try{
1729
+ $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1730
+ if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
1731
+ return true;
1732
+ } else {
1733
+
1734
+ return array(
1735
+ 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
1736
+ 'partial' => 1
1737
+ );
1738
+ }
1739
+
1740
+ }catch (Exception $e){
1741
+ $err = $e->getMessage();
1742
+ if($err){
1743
+ return array(
1744
+ 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
1745
+ );
1746
+ } else {
1747
+ return array(
1748
+ 'error' => 'Failed to upload to Amazon S3.'
1749
+ );
1750
+ }
1751
+ }
1752
+
1753
+ } else {
1754
+ return array(
1755
+ 'error' => 'You cannot use Amazon S3 on your server. Please enable curl extension first.',
1756
+ 'partial' => 1
1757
+ );
1758
+ }
1759
+ }
1760
+
1761
+ function remove_amazons3_backup($args)
1762
+ {
1763
+ if ($this->mmb_function_exists('curl_init')) {
1764
+ require_once('lib/s3.php');
1765
+ extract($args);
1766
+ if ($as3_site_folder == true)
1767
+ $as3_directory .= '/' . $this->site_name;
1768
+ $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1769
+ try{
1770
+ $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1771
+ $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
1772
+ } catch (Exception $e){
1773
+
1774
+ }
1775
+ }
1776
+ }
1777
+
1778
+ function get_amazons3_backup($args)
1779
+ {
1780
+ require_once('lib/s3.php');
1781
+ extract($args);
1782
+ $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1783
+ $temp = '';
1784
+ try{
1785
+ $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1786
+ if ($as3_site_folder == true)
1787
+ $as3_directory .= '/' . $this->site_name;
1788
+
1789
+ $temp = ABSPATH . 'mwp_temp_backup.zip';
1790
+ $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
1791
+ } catch (Exception $e){
1792
+ return $temp;
1793
+ }
1794
+ return $temp;
1795
+ }
1796
+
1797
+ function schedule_next($type, $schedule)
1798
+ {
1799
+ $schedule = explode("|", $schedule);
1800
+
1801
+ if (empty($schedule))
1802
+ return false;
1803
+ switch ($type) {
1804
+
1805
+ case 'daily':
1806
+
1807
+ if (isset($schedule[1]) && $schedule[1]) {
1808
+ $delay_time = $schedule[1] * 60;
1809
+ }
1810
+
1811
+ $current_hour = date("H");
1812
+ $schedule_hour = $schedule[0];
1813
+ if ($current_hour >= $schedule_hour)
1814
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
1815
+ else
1816
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1817
+ break;
1818
+
1819
+
1820
+ case 'weekly':
1821
+ if (isset($schedule[2]) && $schedule[2]) {
1822
+ $delay_time = $schedule[2] * 60;
1823
+ }
1824
+ $current_weekday = date('w');
1825
+ $schedule_weekday = $schedule[1];
1826
+ $current_hour = date("H");
1827
+ $schedule_hour = $schedule[0];
1828
+
1829
+ if ($current_weekday > $schedule_weekday)
1830
+ $weekday_offset = 7 - ($week_day - $task_schedule[1]);
1831
+ else
1832
+ $weekday_offset = $schedule_weekday - $current_weekday;
1833
+
1834
+
1835
+ if (!$weekday_offset) { //today is scheduled weekday
1836
+ if ($current_hour >= $schedule_hour)
1837
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
1838
+ else
1839
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1840
+ } else {
1841
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
1842
+ }
1843
+
1844
+ break;
1845
+
1846
+ case 'monthly':
1847
+ if (isset($schedule[2]) && $schedule[2]) {
1848
+ $delay_time = $schedule[2] * 60;
1849
+ }
1850
+ $current_monthday = date('j');
1851
+ $schedule_monthday = $schedule[1];
1852
+ $current_hour = date("H");
1853
+ $schedule_hour = $schedule[0];
1854
+
1855
+ if ($current_monthday > $schedule_monthday) {
1856
+ $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1857
+ } else if ($current_monthday < $schedule_monthday) {
1858
+ $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1859
+ } else if ($current_monthday == $schedule_monthday) {
1860
+ if ($current_hour >= $schedule_hour)
1861
+ $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1862
+ else
1863
+ $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1864
+ break;
1865
+ }
1866
+
1867
+ break;
1868
+ default:
1869
+ break;
1870
+ }
1871
+
1872
+ if (isset($delay_time) && $delay_time) {
1873
+ $time += $delay_time;
1874
+ }
1875
+
1876
+ return $time;
1877
+
1878
+ }
1879
+
1880
+ //Parse task arguments for info on master
1881
+ function get_backup_stats()
1882
+ {
1883
+ $stats = array();
1884
+ $tasks = $this->tasks;
1885
+ if (is_array($tasks) && !empty($tasks)) {
1886
+ foreach ($tasks as $task_name => $info) {
1887
+ if (is_array($info['task_results']) && !empty($info['task_results'])) {
1888
+ foreach ($info['task_results'] as $key => $result) {
1889
+ if (isset($result['server']) && !isset($result['error'])) {
1890
+ if (!file_exists($result['server']['file_path'])) {
1891
+ $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
1892
+ }
1893
+ }
1894
+ }
1895
+ }
1896
+ if (is_array($info['task_results']))
1897
+ $stats[$task_name] = array_values($info['task_results']);
1898
+
1899
+ }
1900
+ }
1901
+ return $stats;
1902
+ }
1903
+
1904
+ function get_next_schedules()
1905
+ {
1906
+ $stats = array();
1907
+ $tasks = $this->tasks;
1908
+ if (is_array($tasks) && !empty($tasks)) {
1909
+ foreach ($tasks as $task_name => $info) {
1910
+ $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
1911
+ }
1912
+ }
1913
+ return $stats;
1914
+ }
1915
+
1916
+ function remove_old_backups($task_name)
1917
+ {
1918
+
1919
+ //Check for previous failed backups first
1920
+ $this->cleanup();
1921
+
1922
+ //Remove by limit
1923
+ $backups = $this->tasks;
1924
+ if ($task_name == 'Backup Now') {
1925
+ $num = 0;
1926
+ } else {
1927
+ $num = 1;
1928
+ }
1929
+
1930
+
1931
+ if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
1932
+ //how many to remove ?
1933
+ $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
1934
+ for ($i = 0; $i < $remove_num; $i++) {
1935
+ //Remove from the server
1936
+ if (isset($backups[$task_name]['task_results'][$i]['server'])) {
1937
+ @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
1938
+ }
1939
+
1940
+ //Remove from ftp
1941
+ if (isset($backups[$task_name]['task_results'][$i]['ftp']) && isset($backups[$task_name]['task_args']['account_info']['mwp_ftp'])) {
1942
+ $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
1943
+ $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
1944
+ $args['backup_file'] = $ftp_file;
1945
+ $this->remove_ftp_backup($args);
1946
+ }
1947
+
1948
+ if (isset($backups[$task_name]['task_results'][$i]['amazons3']) && isset($backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
1949
+ $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
1950
+ $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1951
+ $args['backup_file'] = $amazons3_file;
1952
+ $this->remove_amazons3_backup($args);
1953
+ }
1954
+
1955
+ if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
1956
+ //To do: dropbox remove
1957
+ $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
1958
+ $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
1959
+ $args['backup_file'] = $dropbox_file;
1960
+ $this->remove_dropbox_backup($args);
1961
+ }
1962
+
1963
+ //Remove database backup info
1964
+ unset($backups[$task_name]['task_results'][$i]);
1965
+
1966
+ } //end foreach
1967
+
1968
+ if (is_array($backups[$task_name]['task_results']))
1969
+ $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
1970
+ else
1971
+ $backups[$task_name]['task_results']=array();
1972
+
1973
+ $this->update_tasks($backups);
1974
+ //update_option('mwp_backup_tasks', $backups);
1975
+ }
1976
+ }
1977
+
1978
+ /**
1979
+ * Delete specified backup
1980
+ * Args: $task_name, $result_id
1981
+ */
1982
+
1983
+ function delete_backup($args)
1984
+ {
1985
+ if (empty($args))
1986
+ return false;
1987
+ extract($args);
1988
+
1989
+ $tasks = $this->tasks;
1990
+ $task = $tasks[$task_name];
1991
+ $backups = $task['task_results'];
1992
+ $backup = $backups[$result_id];
1993
+
1994
+ if (isset($backup['server'])) {
1995
+ @unlink($backup['server']['file_path']);
1996
+ }
1997
+
1998
+ //Remove from ftp
1999
+ if (isset($backup['ftp'])) {
2000
+ $ftp_file = $backup['ftp'];
2001
+ $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
2002
+ $args['backup_file'] = $ftp_file;
2003
+ $this->remove_ftp_backup($args);
2004
+ }
2005
+
2006
+ if (isset($backup['amazons3'])) {
2007
+ $amazons3_file = $backup['amazons3'];
2008
+ $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
2009
+ $args['backup_file'] = $amazons3_file;
2010
+ $this->remove_amazons3_backup($args);
2011
+ }
2012
+
2013
+ if (isset($backup['dropbox'])) {
2014
+ $dropbox_file = $backup['dropbox'];
2015
+ $args = $tasks[$task_name]['task_args']['account_info']['mwp_dropbox'];
2016
+ $args['backup_file'] = $dropbox_file;
2017
+ $this->remove_dropbox_backup($args);
2018
+ }
2019
+
2020
+ unset($backups[$result_id]);
2021
+
2022
+ if (count($backups)) {
2023
+ $tasks[$task_name]['task_results'] = $backups;
2024
+ } else {
2025
+ unset($tasks[$task_name]['task_results']);
2026
+ }
2027
+
2028
+ $this->update_tasks($tasks);
2029
+ //update_option('mwp_backup_tasks', $tasks);
2030
+ return true;
2031
+
2032
+ }
2033
+
2034
+ function cleanup()
2035
+ {
2036
+ $tasks = $this->tasks;
2037
+ $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
2038
+ $backup_folder_new = MWP_BACKUP_DIR . '/';
2039
+ $files = glob($backup_folder . "*");
2040
+ $new = glob($backup_folder_new . "*");
2041
+
2042
+ //Failed db files first
2043
+ $db_folder = MWP_DB_DIR . '/';
2044
+ $db_files = glob($db_folder . "*");
2045
+ if (is_array($db_files) && !empty($db_files)) {
2046
+ foreach ($db_files as $file) {
2047
+ @unlink($file);
2048
+ }
2049
+ @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
2050
+ @rmdir(MWP_DB_DIR);
2051
+ }
2052
+
2053
+
2054
+ //clean_old folder?
2055
+ if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
2056
+ foreach ($files as $file) {
2057
+ @unlink($file);
2058
+ }
2059
+ @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
2060
+ @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
2061
+ }
2062
+
2063
+
2064
+ foreach ($new as $b) {
2065
+ $files[] = $b;
2066
+ }
2067
+ $deleted = array();
2068
+
2069
+ if (is_array($files) && count($files)) {
2070
+ $results = array();
2071
+ if (!empty($tasks)) {
2072
+ foreach ((array) $tasks as $task) {
2073
+ if (isset($task['task_results']) && count($task['task_results'])) {
2074
+ foreach ($task['task_results'] as $backup) {
2075
+ if (isset($backup['server'])) {
2076
+ $results[] = $backup['server']['file_path'];
2077
+ }
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2082
+
2083
+ $num_deleted = 0;
2084
+ foreach ($files as $file) {
2085
+ if (!in_array($file, $results) && basename($file) != 'index.php') {
2086
+ @unlink($file);
2087
+ $deleted[] = basename($file);
2088
+ $num_deleted++;
2089
+ }
2090
+ }
2091
+ }
2092
+
2093
+
2094
+
2095
+ return $deleted;
2096
+ }
2097
+
2098
+
2099
+ function remote_backup_now($args)
2100
+ {
2101
+ $this->set_memory();
2102
+ if (!empty($args))
2103
+ extract($args);
2104
+
2105
+ $tasks = $this->tasks;
2106
+ $task = $tasks['Backup Now'];
2107
+
2108
+ if (!empty($task)) {
2109
+ extract($task['task_args']);
2110
+ }
2111
+
2112
+ $results = $task['task_results'];
2113
+
2114
+ if (is_array($results) && count($results)) {
2115
+ $backup_file = $results[count($results) - 1]['server']['file_path'];
2116
+ }
2117
+
2118
+ if ($backup_file && file_exists($backup_file)) {
2119
+ //FTP, Amazon S3 or Dropbox
2120
+ if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
2121
+ $account_info['mwp_ftp']['backup_file'] = $backup_file;
2122
+ $return = $this->ftp_backup($account_info['mwp_ftp']);
2123
+ }
2124
+
2125
+ if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
2126
+ $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
2127
+ $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
2128
+ }
2129
+
2130
+ if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
2131
+ $account_info['mwp_dropbox']['backup_file'] = $backup_file;
2132
+ $return = $this->dropbox_backup($account_info['mwp_dropbox']);
2133
+ }
2134
+
2135
+ if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
2136
+ $account_info['mwp_email']['file_path'] = $backup_file;
2137
+ $account_info['mwp_email']['task_name'] = 'Backup Now';
2138
+ $return = $this->email_backup($account_info['mwp_email']);
2139
+ }
2140
+
2141
+ @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
2142
+ if ($return == true && $del_host_file) {
2143
+ @unlink($backup_file);
2144
+ unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
2145
+ $this->update_tasks($tasks);
2146
+ //update_option('mwp_backup_tasks', $tasks);
2147
+ }
2148
+
2149
+
2150
+
2151
+ } else {
2152
+ $return = array(
2153
+ 'error' => 'Backup file not found on your server. Please try again.'
2154
+ );
2155
+ }
2156
+
2157
+ return $return;
2158
+
2159
+ }
2160
+
2161
+ function validate_task($args, $url)
2162
+ {
2163
+ if (!class_exists('WP_Http')) {
2164
+ include_once(ABSPATH . WPINC . '/class-http.php');
2165
+ }
2166
+ $params = array();
2167
+ $params['body'] = $args;
2168
+ $result = wp_remote_post($url, $params);
2169
+ if (is_array($result) && $result['body'] == 'mwp_delete_task') {
2170
+ //$tasks = $this->get_backup_settings();
2171
+ $tasks = $this->tasks;
2172
+ unset($tasks[$args['task_name']]);
2173
+ $this->update_tasks($tasks);
2174
+ $this->cleanup();
2175
+ exit;
2176
+ } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
2177
+ return 'paused';
2178
+ }
2179
+
2180
+ return 'ok';
2181
+ }
2182
+
2183
+ function update_status($task_name, $status, $completed = false)
2184
+ {
2185
+ /* Statuses:
2186
+ 0 - Backup started
2187
+ 1 - DB dump
2188
+ 2 - DB ZIP
2189
+ 3 - Files ZIP
2190
+ 4 - Amazon S3
2191
+ 5 - Dropbox
2192
+ 6 - FTP
2193
+ 7 - Email
2194
+ 100 - Finished
2195
+ */
2196
+ if ($task_name != 'Backup Now') {
2197
+ $tasks = $this->tasks;
2198
+ $index = count($tasks[$task_name]['task_results']) - 1;
2199
+ if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
2200
+ $tasks[$task_name]['task_results'][$index]['status'] = array();
2201
+ }
2202
+ if (!$completed) {
2203
+ $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
2204
+ } else {
2205
+ $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
2206
+ $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
2207
+ }
2208
+
2209
+ $this->update_tasks($tasks);
2210
+ //update_option('mwp_backup_tasks',$tasks);
2211
+ }
2212
+ }
2213
+
2214
+ function update_tasks($tasks)
2215
+ {
2216
+ $this->tasks = $tasks;
2217
+ update_option('mwp_backup_tasks', $tasks);
2218
+ }
2219
+
2220
+ function wpdb_reconnect(){
2221
+ global $wpdb;
2222
+ //Reconnect to avoid timeout problem after ZIP files
2223
+ if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
2224
+ @mysql_close($wpdb->dbh);
2225
+ $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2226
+ wp_set_wpdb_vars();
2227
+ }
2228
+ }
2229
+
2230
+ function replace_htaccess($url)
2231
+ {
2232
+ $file = @file_get_contents(ABSPATH.'.htaccess');
2233
+ if ($file && strlen($file)) {
2234
+ $args = parse_url($url);
2235
+ $string = rtrim($args['path'], "/");
2236
+ $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
2237
+ $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
2238
+ $file = preg_replace($regex, $replace, $file);
2239
+ @file_put_contents(ABSPATH.'.htaccess', $file);
2240
+ }
2241
+ }
2242
+
2243
+ function check_cron_remove(){
2244
+ if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
2245
+ wp_clear_scheduled_hook('mwp_backup_tasks');
2246
+ exit;
2247
+ }
2248
+ }
2249
+
2250
+ public static function readd_tasks( $params = array() ){
2251
+ global $mmb_core;
2252
+
2253
+ if( empty($params) || !isset($params['backups']) )
2254
+ return $params;
2255
+
2256
+ $before = array();
2257
+ $tasks = $params['backups'];
2258
+ if( !empty($tasks) ){
2259
+ $mmb_backup = new MMB_Backup();
2260
+
2261
+ if( function_exists( 'wp_next_scheduled' ) ){
2262
+ if ( !wp_next_scheduled('mwp_backup_tasks') ) {
2263
+ wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
2264
+ }
2265
+ }
2266
+
2267
+ foreach( $tasks as $task ){
2268
+ $before[$task['task_name']] = array();
2269
+
2270
+ if(isset($task['secure'])){
2271
+ if($decrypted = $mmb_core->_secure_data($task['secure'])){
2272
+ $decrypted = maybe_unserialize($decrypted);
2273
+ if(is_array($decrypted)){
2274
+ foreach($decrypted as $key => $val){
2275
+ if(!is_numeric($key))
2276
+ $task[$key] = $val;
2277
+ }
2278
+ unset($task['secure']);
2279
+ } else
2280
+ $task['secure'] = $decrypted;
2281
+ }
2282
+
2283
+ }
2284
+ if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from master first time(secure data)
2285
+ $task['args']['account_info'] = $task['account_info'];
2286
+ }
2287
+
2288
+ $before[$task['task_name']]['task_args'] = $task['args'];
2289
+ $before[$task['task_name']]['task_args']['next'] = $mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
2290
+ }
2291
+ }
2292
+ update_option('mwp_backup_tasks', $before);
2293
+
2294
+ unset($params['backups']);
2295
+ return $params;
2296
+ }
2297
+ }
2298
+
2299
+ if( function_exists('add_filter') ){
2300
+ add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
2301
+ }
2302
  ?>
comment.class.php CHANGED
@@ -1,45 +1,252 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * post.class.php
5
- *
6
- * Create remote post
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "comment.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Comment extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- function change_status($args)
23
- {
24
-
25
- global $wpdb;
26
- $comment_id = $args['comment_id'];
27
- $status = $args['status'];
28
-
29
- if ( 'approve' == $status )
30
- $status_sql = '1';
31
- elseif ( 'unapprove' == $status )
32
- $status_sql = '0';
33
- elseif ( 'spam' == $status )
34
- $status_sql = 'spam';
35
- elseif ( 'trash' == $status )
36
- $status_sql = 'trash';
37
- $sql = "update ".$wpdb->prefix."comments set comment_approved = '%s' where comment_ID = '%s'";
38
- $success = $wpdb->query($wpdb->prepare($sql, array($status_sql, $comment_id)));
39
-
40
-
41
- return $success;
42
- }
43
-
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * comment.class.php
5
+ *
6
+ * Get comments
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "comment.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Comment extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ function change_status($args)
23
+ {
24
+
25
+ global $wpdb;
26
+ $comment_id = $args['comment_id'];
27
+ $status = $args['status'];
28
+
29
+ if ( 'approve' == $status )
30
+ $status_sql = '1';
31
+ elseif ( 'unapprove' == $status )
32
+ $status_sql = '0';
33
+ elseif ( 'spam' == $status )
34
+ $status_sql = 'spam';
35
+ elseif ( 'trash' == $status )
36
+ $status_sql = 'trash';
37
+ $sql = "update ".$wpdb->prefix."comments set comment_approved = '%s' where comment_ID = '%s'";
38
+ $success = $wpdb->query($wpdb->prepare($sql, array($status_sql, $comment_id)));
39
+
40
+
41
+ return $success;
42
+ }
43
+
44
+ function get_comments($args){
45
+ global $wpdb;
46
+
47
+ $where='';
48
+
49
+ extract($args);
50
+
51
+ if(!empty($filter_comments))
52
+ {
53
+ $where.=" AND (c.comment_author LIKE '%".mysql_real_escape_string($filter_comments)."%' OR c.comment_content LIKE '%".mysql_real_escape_string($filter_comments)."%')";
54
+ }
55
+ $comment_array = array();
56
+ $comment_statuses = array('approved', 'pending', 'spam', 'trash');
57
+ foreach ($args as $checkbox => $checkbox_val)
58
+ {
59
+ if($checkbox_val=="on") {
60
+ $status_val = str_replace("mwp_get_comments_","",$checkbox);
61
+ if($status_val == 'approved'){
62
+ $status_val = 1;
63
+ }elseif($status_val == 'pending'){
64
+ $status_val = 0;
65
+ }
66
+ $comment_array[]="'".$status_val."'";
67
+ }
68
+ }
69
+ if(!empty($comment_array))
70
+ {
71
+ $where.=" AND c.comment_approved IN (".implode(",",$comment_array).")";
72
+ }
73
+
74
+ $sql_query = "$wpdb->comments as c, $wpdb->posts as p WHERE c.comment_post_ID = p.ID ".$where;
75
+
76
+ $comments_total = $wpdb->get_results("SELECT count(*) as total_comments FROM ".$sql_query);
77
+ $total=$comments_total[0]->total_comments;
78
+ $comments_approved = $this->comment_total();
79
+
80
+ $query_comments = $wpdb->get_results("SELECT c.comment_ID, c.comment_post_ID, c.comment_author, c.comment_author_email, c.comment_author_url, c.comment_author_IP, c.comment_date, c.comment_content, c.comment_approved, c.comment_parent, p.post_title, p.post_type, p.guid FROM ".$sql_query." ORDER BY c.comment_date DESC LIMIT 500");
81
+ $comments = array();
82
+ foreach ( $query_comments as $comments_info )
83
+ {
84
+ $comment_total_approved = 0;
85
+ if(isset($comments_approved[$comments_info->comment_post_ID]['approved'])){
86
+ $comment_total_approved = $comments_approved[$comments_info->comment_post_ID]['approved'];
87
+ }
88
+ $comment_total_pending = 0;
89
+ if(isset($comments_approved[$comments_info->comment_post_ID]['pending'])){
90
+ $comment_total_pending = $comments_approved[$comments_info->comment_post_ID]['pending'];
91
+ }
92
+ $comment_parent_author = '';
93
+ if($comments_info->comment_parent > 0){
94
+ $select_parent_author = "SELECT comment_author FROM $wpdb->comments WHERE comment_ID = ".$comments_info->comment_parent;
95
+ $select_parent_author_res = $wpdb->get_row($select_parent_author);
96
+ $comment_parent_author = $select_parent_author_res->comment_author;
97
+ }
98
+
99
+ $comments[$comments_info->comment_ID] = array(
100
+ "comment_post_ID" => $comments_info->comment_post_ID,
101
+ "comment_author" => $comments_info->comment_author,
102
+ "comment_author_email" => $comments_info->comment_author_email,
103
+ "comment_author_url" => $comments_info->comment_author_url,
104
+ "comment_author_IP" => $comments_info->comment_author_IP,
105
+ "comment_date" => $comments_info->comment_date,
106
+ "comment_content" => $comments_info->comment_content,
107
+ "comment_approved" => $comments_info->comment_approved,
108
+ "comment_parent" => $comments_info->comment_parent,
109
+ "comment_parent_author" => $comment_parent_author,
110
+ "post_title" => $comments_info->post_title,
111
+ "post_type" => $comments_info->post_type,
112
+ "guid" => $comments_info->guid,
113
+ "comment_total_approved" => $comment_total_approved,
114
+ "comment_total_pending" => $comment_total_pending,
115
+ );
116
+ }
117
+
118
+ return array('comments' => $comments, 'total' => $total);
119
+ }
120
+
121
+ function comment_total(){
122
+ global $wpdb;
123
+ $totals = array();
124
+ $select_total_approved = "SELECT COUNT(*) as total, p.ID FROM $wpdb->comments as c, $wpdb->posts as p WHERE c.comment_post_ID = p.ID AND c.comment_approved = 1 GROUP BY p.ID";
125
+ $select_total_approved_res = $wpdb->get_results($select_total_approved);
126
+
127
+ if(!empty($select_total_approved_res)){
128
+ foreach($select_total_approved_res as $row){
129
+ $totals[$row->ID]['approved'] = $row->total;
130
+ }
131
+ }
132
+ $select_total_pending = "SELECT COUNT(*) as total, p.ID FROM $wpdb->comments as c, $wpdb->posts as p WHERE c.comment_post_ID = p.ID AND c.comment_approved = 0 GROUP BY p.ID";
133
+ $select_total_pending_res = $wpdb->get_results($select_total_pending);
134
+ if(!empty($select_total_pending_res)){
135
+ foreach($select_total_pending_res as $row){
136
+ $totals[$row->ID]['pending'] = $row->total;
137
+ }
138
+ }
139
+
140
+ return $totals;
141
+ }
142
+
143
+ function action_comment($args){
144
+ global $wpdb;
145
+ extract($args);
146
+ if($docomaction == 'approve'){
147
+ $docomaction = '1';
148
+ }else if($docomaction == 'unapprove' || $docomaction == 'untrash' || $docomaction == 'unspam'){
149
+ $docomaction = '0';
150
+ }
151
+
152
+ if(!empty($comment_id)){
153
+ if($docomaction == 'delete'){
154
+ $update_query = "DELETE FROM $wpdb->comments WHERE comment_ID = ".$comment_id;
155
+ $delete_query = "DELETE FROM $wpdb->commentmeta WHERE comment_id = ".$comment_id;
156
+ $wpdb->query($delete_query);
157
+ }else{
158
+ $update_query = "UPDATE $wpdb->comments SET comment_approved = '".$docomaction."' WHERE comment_ID = ".$comment_id;
159
+ }
160
+ $wpdb->query($update_query);
161
+
162
+ return 'Comment updated.';
163
+ }else{
164
+ return 'No ID...';
165
+ }
166
+ }
167
+
168
+ function bulk_action_comments($args){
169
+ global $wpdb;
170
+ extract($args);
171
+
172
+ if($docomaction=='delete'){
173
+ $update_query_intro = "DELETE FROM $wpdb->comments WHERE comment_ID = ";
174
+ }else{
175
+ if($docomaction=='unapprove' || $docomaction == 'untrash' || $docomaction == 'unspam'){
176
+ $docomaction = '0';
177
+ }else if($docomaction == 'approve'){
178
+ $docomaction = '1';
179
+ }
180
+ $update_query_intro = "UPDATE $wpdb->comments SET comment_approved = '".$docomaction."' WHERE comment_ID = ";
181
+ }
182
+ foreach($args as $key=>$val){
183
+
184
+ if(!empty($val) && is_numeric($val))
185
+ {
186
+ if($docomaction=='delete'){
187
+ $delete_query = "DELETE FROM $wpdb->commentmeta WHERE comment_id = ".$val;
188
+ $wpdb->query($delete_query);
189
+ }
190
+ $update_query = $update_query_intro.$val;
191
+
192
+ $wpdb->query($update_query);
193
+ }
194
+ }
195
+ return "comments updated";
196
+ }
197
+
198
+ function reply_comment($args){
199
+ global $wpdb, $current_user;
200
+ extract($args);
201
+ $comments = array();
202
+
203
+ if(!empty($comment_id) && !empty($reply_text)){
204
+ $admins = get_userdata($current_user->ID);
205
+ $now = time();
206
+ $insert_reply = "INSERT INTO $wpdb->comments(comment_post_ID, comment_author, comment_author_email, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_karma, comment_approved, comment_agent, comment_parent, user_id) VALUES(".$post_id.", '".$admins->user_login."', '".$admins->user_email."', '".$admins->user_url."', '".$_SERVER['REMOTE_ADDR']."', NOW(), NOW(), '%s', 0, 1, '".$_SERVER['HTTP_USER_AGENT']."', ".$comment_id.", ".$current_user->ID.")";
207
+ $insert_reply_res = $wpdb->query($wpdb->prepare($insert_reply, base64_decode($reply_text)));
208
+ $lastid = $wpdb->insert_id;
209
+
210
+ $comments_approved = $this->comment_total();
211
+
212
+ $comment_total_approved = 0;
213
+ if(isset($comments_approved[$post_id]['approved'])){
214
+ $comment_total_approved = $comments_approved[$post_id]['approved'];
215
+ }
216
+ $comment_total_pending = 0;
217
+ if(isset($comments_approved[$post_id]['pending'])){
218
+ $comment_total_pending = $comments_approved[$post_id]['pending'];
219
+ }
220
+
221
+ $comment_parent_author = '';
222
+ if($comment_id > 0){
223
+ $select_parent_author = "SELECT c.comment_author, p.post_title, p.post_type, p.guid FROM $wpdb->comments as c, $wpdb->posts as p WHERE c.comment_post_ID = p.ID AND c.comment_ID = ".$comment_id;
224
+ $select_parent_author_res = $wpdb->get_row($select_parent_author);
225
+ $comment_parent_author = $select_parent_author_res->comment_author;
226
+ }
227
+
228
+ $comments[$lastid] = array(
229
+ "comment_post_ID" => $post_id,
230
+ "comment_author" => $admins->user_login,
231
+ "comment_author_email" => $admins->user_email,
232
+ "comment_author_url" => $admins->user_url,
233
+ "comment_author_IP" => $_SERVER['REMOTE_ADDR'],
234
+ "comment_date" => $now,
235
+ "comment_content" => $reply_text,
236
+ "comment_approved" => '1',
237
+ "comment_parent" => $comment_id,
238
+ "comment_parent_author" => $comment_parent_author,
239
+ "post_title" => $select_parent_author_res->post_title,
240
+ "post_type" => $select_parent_author_res->post_type,
241
+ "guid" => $select_parent_author_res->guid,
242
+ "comment_total_approved" => $comment_total_approved,
243
+ "comment_total_pending" => $comment_total_pending,
244
+ );
245
+
246
+
247
+ }
248
+ return $comments;
249
+ }
250
+
251
+ }
252
  ?>
core.class.php CHANGED
@@ -1,667 +1,671 @@
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
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "core.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Core extends MMB_Helper
16
- {
17
- var $name;
18
- var $slug;
19
- var $settings;
20
- var $remote_client;
21
- var $comment_instance;
22
- var $plugin_instance;
23
- var $theme_instance;
24
- var $wp_instance;
25
- var $post_instance;
26
- var $stats_instance;
27
- var $search_instance;
28
- var $links_instance;
29
- var $user_instance;
30
- var $backup_instance;
31
- var $installer_instance;
32
- var $mmb_multisite;
33
- var $network_admin_install;
34
- private $action_call;
35
- private $action_params;
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;
56
- $this->network_admin_install = get_option('mmb_network_admin_install');
57
- }
58
- } else if (!empty($wpmu_version)) {
59
- $this->mmb_multisite = $blog_id;
60
- $this->network_admin_install = get_option('mmb_network_admin_install');
61
- } else {
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 ){
69
- if( is_network_admin() && $this->network_admin_install == '1'){
70
- add_action('network_admin_notices', array( &$this, 'network_admin_notice' ));
71
- } else if( $this->network_admin_install != '1' ){
72
- $parent_key = $this->get_parent_blog_option('_worker_public_key');
73
- if(empty($parent_key))
74
- add_action('admin_notices', array( &$this, 'admin_notice' ));
75
- }
76
- } else {
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',
95
- 'remove_site' => 'mmb_remove_site',
96
- 'backup_clone' => 'mmb_backup_now',
97
- 'restore' => 'mmb_restore_now',
98
- 'optimize_tables' => 'mmb_optimize_tables',
99
- 'check_wp_version' => 'mmb_wp_checkversion',
100
- 'create_post' => 'mmb_post_create',
101
- 'update_worker' => 'mmb_update_worker_plugin',
102
- 'change_comment_status' => 'mmb_change_comment_status',
103
- 'change_post_status' => 'mmb_change_post_status',
104
- 'get_comment_stats' => 'mmb_comment_stats_get',
105
- 'install_addon' => 'mmb_install_addon',
106
- 'get_links' => 'mmb_get_links',
107
- 'add_link' => 'mmb_add_link',
108
- 'delete_link' => 'mmb_delete_link',
109
- 'delete_links' => 'mmb_delete_links',
110
- 'add_user' => 'mmb_add_user',
111
- 'email_backup' => 'mmb_email_backup',
112
- 'check_backup_compat' => 'mmb_check_backup_compat',
113
- 'scheduled_backup' => 'mmb_scheduled_backup',
114
- 'run_task' => 'mmb_run_task_now',
115
- 'execute_php_code' => 'mmb_execute_php_code',
116
- 'delete_backup' => 'mmm_delete_backup',
117
- 'remote_backup_now' => 'mmb_remote_backup_now',
118
- 'set_notifications' => 'mmb_set_notifications',
119
- 'clean_orphan_backups' => 'mmb_clean_orphan_backups',
120
- 'get_users' => 'mmb_get_users',
121
- 'edit_users' => 'mmb_edit_users',
122
- 'get_posts' => 'mmb_get_posts',
123
- 'delete_post' => 'mmb_delete_post',
124
- 'delete_posts' => 'mmb_delete_posts',
125
- 'edit_posts' => 'mmb_edit_posts',
126
- 'get_pages' => 'mmb_get_pages',
127
- 'delete_page' => 'mmb_delete_page',
128
- 'get_plugins_themes' => 'mmb_get_plugins_themes',
129
- 'edit_plugins_themes' => 'mmb_edit_plugins_themes',
130
- 'worker_brand' => 'mmb_worker_brand',
131
- 'set_alerts' => 'mmb_set_alerts',
132
- 'maintenance' => 'mmb_maintenance_mode'
133
- );
134
-
135
- add_action('rightnow_end', array( &$this, 'add_right_now_info' ));
136
- add_action('admin_init', array(&$this,'admin_actions'));
137
- add_action('init', array( &$this, 'mmb_remote_action'), 9999);
138
- add_action('setup_theme', 'mmb_parse_request');
139
- add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
140
- add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
141
-
142
- }
143
-
144
- function mmb_remote_action(){
145
- if($this->action_call != null){
146
- $params = isset($this->action_params) && $this->action_params != null ? $this->action_params : array();
147
- call_user_func($this->action_call, $params);
148
- }
149
- }
150
-
151
- function register_action_params( $action = false, $params = array() ){
152
-
153
- if(isset($this->mmb_pre_init_actions[$action]) && function_exists($this->mmb_pre_init_actions[$action])){
154
- call_user_func($this->mmb_pre_init_actions[$action], $params);
155
- }
156
-
157
- if(isset($this->mmb_init_actions[$action]) && function_exists($this->mmb_init_actions[$action])){
158
- $this->action_call = $this->mmb_init_actions[$action];
159
- $this->action_params = $params;
160
-
161
- if( isset($this->mmb_pre_init_filters[$action]) && !empty($this->mmb_pre_init_filters[$action])){
162
- global $mmb_filters;
163
-
164
- foreach($this->mmb_pre_init_filters[$action] as $_name => $_functions){
165
- if(!empty($_functions)){
166
- $data = array();
167
-
168
- foreach($_functions as $_k => $_callback){
169
- if(is_array($_callback) && method_exists($_callback[0], $_callback[1]) ){
170
- $data = call_user_func( $_callback, $params );
171
- } elseif (is_string($_callback) && function_exists( $_callback )){
172
- $data = call_user_func( $_callback, $params );
173
- }
174
- $mmb_filters[$_name] = isset($mmb_filters[$_name]) && !empty($mmb_filters[$_name]) ? array_merge($mmb_filters[$_name], $data) : $data;
175
- add_filter( $_name, create_function( '$a' , 'global $mmb_filters; return array_merge($a, $mmb_filters["'.$_name.'"]);') );
176
- }
177
- }
178
-
179
- }
180
- }
181
- return true;
182
- }
183
- return false;
184
- }
185
-
186
- /**
187
- * Add notice to network admin dashboard for security reasons
188
- *
189
- */
190
- function network_admin_notice()
191
- {
192
- echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
193
- 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>.
194
- </p></div>';
195
- }
196
-
197
-
198
- /**
199
- * Add notice to admin dashboard for security reasons
200
- *
201
- */
202
- function admin_notice()
203
- {
204
- echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
205
- 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>.
206
- </p></div>';
207
- }
208
-
209
- /**
210
- * Add an item into the Right Now Dashboard widget
211
- * to inform that the blog can be managed remotely
212
- *
213
- */
214
- function add_right_now_info()
215
- {
216
- echo '<div class="mmb-slave-info">
217
- <p>This site can be managed remotely.</p>
218
- </div>';
219
- }
220
-
221
- /**
222
- * Get parent blog options
223
- *
224
- */
225
- private function get_parent_blog_option( $option_name = '' )
226
- {
227
- global $wpdb;
228
- $option = $wpdb->get_var( $wpdb->prepare( "SELECT `option_value` FROM {$wpdb->base_prefix}options WHERE option_name = '{$option_name}' LIMIT 1" ) );
229
- return $option;
230
- }
231
-
232
- /**
233
- * Gets an instance of the Comment class
234
- *
235
- */
236
- function get_comment_instance()
237
- {
238
- if (!isset($this->comment_instance)) {
239
- $this->comment_instance = new MMB_Comment();
240
- }
241
-
242
- return $this->comment_instance;
243
- }
244
-
245
- /**
246
- * Gets an instance of the Plugin class
247
- *
248
- */
249
- function get_plugin_instance()
250
- {
251
- if (!isset($this->plugin_instance)) {
252
- $this->plugin_instance = new MMB_Plugin();
253
- }
254
-
255
- return $this->plugin_instance;
256
- }
257
-
258
- /**
259
- * Gets an instance of the Theme class
260
- *
261
- */
262
- function get_theme_instance()
263
- {
264
- if (!isset($this->theme_instance)) {
265
- $this->theme_instance = new MMB_Theme();
266
- }
267
-
268
- return $this->theme_instance;
269
- }
270
-
271
-
272
- /**
273
- * Gets an instance of MMB_Post class
274
- *
275
- */
276
- function get_post_instance()
277
- {
278
- if (!isset($this->post_instance)) {
279
- $this->post_instance = new MMB_Post();
280
- }
281
-
282
- return $this->post_instance;
283
- }
284
-
285
- /**
286
- * Gets an instance of Blogroll class
287
- *
288
- */
289
- function get_blogroll_instance()
290
- {
291
- if (!isset($this->blogroll_instance)) {
292
- $this->blogroll_instance = new MMB_Blogroll();
293
- }
294
-
295
- return $this->blogroll_instance;
296
- }
297
-
298
-
299
-
300
- /**
301
- * Gets an instance of the WP class
302
- *
303
- */
304
- function get_wp_instance()
305
- {
306
- if (!isset($this->wp_instance)) {
307
- $this->wp_instance = new MMB_WP();
308
- }
309
-
310
- return $this->wp_instance;
311
- }
312
-
313
- /**
314
- * Gets an instance of User
315
- *
316
- */
317
- function get_user_instance()
318
- {
319
- if (!isset($this->user_instance)) {
320
- $this->user_instance = new MMB_User();
321
- }
322
-
323
- return $this->user_instance;
324
- }
325
-
326
- /**
327
- * Gets an instance of stats class
328
- *
329
- */
330
- function get_stats_instance()
331
- {
332
- if (!isset($this->stats_instance)) {
333
- $this->stats_instance = new MMB_Stats();
334
- }
335
- return $this->stats_instance;
336
- }
337
- /**
338
- * Gets an instance of search class
339
- *
340
- */
341
- function get_search_instance()
342
- {
343
- if (!isset($this->search_instance)) {
344
- $this->search_instance = new MMB_Search();
345
- }
346
- //return $this->search_instance;
347
- return $this->search_instance;
348
- }
349
- /**
350
- * Gets an instance of stats class
351
- *
352
- */
353
- function get_backup_instance()
354
- {
355
- if (!isset($this->backup_instance)) {
356
- $this->backup_instance = new MMB_Backup();
357
- }
358
-
359
- return $this->backup_instance;
360
- }
361
-
362
- /**
363
- * Gets an instance of links class
364
- *
365
- */
366
- function get_link_instance()
367
- {
368
- if (!isset($this->link_instance)) {
369
- $this->link_instance = new MMB_Link();
370
- }
371
-
372
- return $this->link_instance;
373
- }
374
-
375
- function get_installer_instance()
376
- {
377
- if (!isset($this->installer_instance)) {
378
- $this->installer_instance = new MMB_Installer();
379
- }
380
- return $this->installer_instance;
381
- }
382
-
383
- /**
384
- * Plugin install callback function
385
- * Check PHP version
386
- */
387
- function install() {
388
-
389
- global $wpdb, $_wp_using_ext_object_cache, $current_user;
390
- $_wp_using_ext_object_cache = false;
391
-
392
- //delete plugin options, just in case
393
- if ($this->mmb_multisite != false) {
394
- $network_blogs = $wpdb->get_results($wpdb->prepare("select `blog_id`, `site_id` from `{$wpdb->blogs}`"));
395
- if(!empty($network_blogs)){
396
- if( is_network_admin() ){
397
- update_option('mmb_network_admin_install', 1);
398
- foreach($network_blogs as $details){
399
- if($details->site_id == $details->blog_id)
400
- update_blog_option($details->blog_id, 'mmb_network_admin_install', 1);
401
- else
402
- update_blog_option($details->blog_id, 'mmb_network_admin_install', -1);
403
-
404
- delete_blog_option($blog_id, '_worker_nossl_key');
405
- delete_blog_option($blog_id, '_worker_public_key');
406
- delete_blog_option($blog_id, '_action_message_id');
407
- }
408
- } else {
409
- update_option('mmb_network_admin_install', -1);
410
- delete_option('_worker_nossl_key');
411
- delete_option('_worker_public_key');
412
- delete_option('_action_message_id');
413
- }
414
- }
415
- } else {
416
- delete_option('_worker_nossl_key');
417
- delete_option('_worker_public_key');
418
- delete_option('_action_message_id');
419
- }
420
-
421
- delete_option('mwp_backup_tasks');
422
- delete_option('mwp_notifications');
423
- delete_option('mwp_worker_brand');
424
- delete_option('mwp_pageview_alerts');
425
-
426
- }
427
-
428
- /**
429
- * Saves the (modified) options into the database
430
- *
431
- */
432
- function save_options( $options = array() ){
433
- global $_mmb_options;
434
-
435
- $_mmb_options = array_merge( $_mmb_options, $options );
436
- update_option('wrksettings', $options);
437
- }
438
-
439
- /**
440
- * Deletes options for communication with master
441
- *
442
- */
443
- function uninstall( $deactivate = false )
444
- {
445
- global $current_user, $wpdb, $_wp_using_ext_object_cache;
446
- $_wp_using_ext_object_cache = false;
447
-
448
- if ($this->mmb_multisite != false) {
449
- $network_blogs = $wpdb->get_col($wpdb->prepare("select `blog_id` from `{$wpdb->blogs}`"));
450
- if(!empty($network_blogs)){
451
- if( is_network_admin() ){
452
- if( $deactivate ) {
453
- delete_option('mmb_network_admin_install');
454
- foreach($network_blogs as $blog_id){
455
- delete_blog_option($blog_id, 'mmb_network_admin_install');
456
- delete_blog_option($blog_id, '_worker_nossl_key');
457
- delete_blog_option($blog_id, '_worker_public_key');
458
- delete_blog_option($blog_id, '_action_message_id');
459
- delete_blog_option($blog_id, 'mwp_maintenace_mode');
460
- delete_blog_option($blog_id, 'mwp_backup_tasks');
461
- delete_blog_option($blog_id, 'mwp_notifications');
462
- delete_blog_option($blog_id, 'mwp_worker_brand');
463
- delete_blog_option($blog_id, 'mwp_pageview_alerts');
464
- delete_blog_option($blog_id, 'mwp_pageview_alerts');
465
- }
466
- }
467
- } else {
468
- if( $deactivate )
469
- delete_option('mmb_network_admin_install');
470
-
471
- delete_option('_worker_nossl_key');
472
- delete_option('_worker_public_key');
473
- delete_option('_action_message_id');
474
- }
475
- }
476
- } else {
477
- delete_option('_worker_nossl_key');
478
- delete_option('_worker_public_key');
479
- delete_option('_action_message_id');
480
- }
481
-
482
- //Delete options
483
- delete_option('mwp_maintenace_mode');
484
- delete_option('mwp_backup_tasks');
485
- delete_option('mwp_notifications');
486
- delete_option('mwp_worker_brand');
487
- delete_option('mwp_pageview_alerts');
488
- wp_clear_scheduled_hook('mwp_backup_tasks');
489
- wp_clear_scheduled_hook('mwp_notifications');
490
- wp_clear_scheduled_hook('mwp_datasend');
491
- }
492
-
493
-
494
- /**
495
- * Constructs a url (for ajax purpose)
496
- *
497
- * @param mixed $base_page
498
- */
499
- function construct_url($params = array(), $base_page = 'index.php')
500
- {
501
- $url = "$base_page?_wpnonce=" . wp_create_nonce($this->slug);
502
- foreach ($params as $key => $value) {
503
- $url .= "&$key=$value";
504
- }
505
-
506
- return $url;
507
- }
508
-
509
- /**
510
- * Worker update
511
- *
512
- */
513
- function update_worker_plugin($params)
514
- {
515
- extract($params);
516
- if ($download_url) {
517
- @include_once ABSPATH . 'wp-admin/includes/file.php';
518
- @include_once ABSPATH . 'wp-admin/includes/misc.php';
519
- @include_once ABSPATH . 'wp-admin/includes/template.php';
520
- @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
521
- @include_once ABSPATH . 'wp-admin/includes/screen.php';
522
-
523
- if (!$this->is_server_writable()) {
524
- return array(
525
- '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>'
526
- );
527
- }
528
-
529
- ob_start();
530
- @unlink(dirname(__FILE__));
531
- $upgrader = new Plugin_Upgrader();
532
- $result = $upgrader->run(array(
533
- 'package' => $download_url,
534
- 'destination' => WP_PLUGIN_DIR,
535
- 'clear_destination' => true,
536
- 'clear_working' => true,
537
- 'hook_extra' => array(
538
- 'plugin' => 'worker/init.php'
539
- )
540
- ));
541
- ob_end_clean();
542
- if (is_wp_error($result) || !$result) {
543
- return array(
544
- 'error' => 'ManageWP Worker plugin could not be updated.'
545
- );
546
- } else {
547
- return array(
548
- 'success' => 'ManageWP Worker plugin successfully updated.'
549
- );
550
- }
551
- }
552
- return array(
553
- 'error' => 'Bad download path for worker installation file.'
554
- );
555
- }
556
-
557
- /**
558
- * Automatically logs in when called from Master
559
- *
560
- */
561
- function automatic_login()
562
- {
563
- $where = isset($_GET['mwp_goto']) ? $_GET['mwp_goto'] : false;
564
- $username = isset($_GET['username']) ? $_GET['username'] : '';
565
- $auto_login = isset($_GET['auto_login']) ? $_GET['auto_login'] : 0;
566
-
567
- if( !function_exists('is_user_logged_in') )
568
- include_once( ABSPATH.'wp-includes/pluggable.php' );
569
-
570
- if (( $auto_login && strlen(trim($username)) && !is_user_logged_in() ) || (isset($this->mmb_multisite) && $this->mmb_multisite )) {
571
- $signature = base64_decode($_GET['signature']);
572
- $message_id = trim($_GET['message_id']);
573
-
574
- $auth = $this->authenticate_message($where . $message_id, $signature, $message_id);
575
- if ($auth === true) {
576
-
577
- if (!headers_sent())
578
- header('P3P: CP="CAO PSA OUR"');
579
-
580
- if(!defined('MMB_USER_LOGIN'))
581
- define('MMB_USER_LOGIN', true);
582
-
583
- $siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
584
- $user = $this->mmb_get_user_info($username);
585
- wp_set_current_user($user->ID);
586
-
587
- if(!defined('COOKIEHASH') || (isset($this->mmb_multisite) && $this->mmb_multisite) )
588
- wp_cookie_constants();
589
-
590
- wp_set_auth_cookie($user->ID);
591
- @mmb_worker_header();
592
-
593
- if((isset($this->mmb_multisite) && $this->mmb_multisite ) || isset($_REQUEST['mwpredirect'])){
594
- if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
595
- wp_safe_redirect(admin_url($where));
596
- exit();
597
- }
598
- }
599
- } else {
600
- wp_die($auth['error']);
601
- }
602
- } elseif( is_user_logged_in() ) {
603
- @mmb_worker_header();
604
- if(isset($_REQUEST['mwpredirect'])){
605
- if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
606
- wp_safe_redirect(admin_url($where));
607
- exit();
608
- }
609
- }
610
- }
611
- }
612
-
613
- function mmb_set_auth_cookie( $auth_cookie ){
614
- if(!defined('MMB_USER_LOGIN'))
615
- return false;
616
-
617
- if( !defined('COOKIEHASH') )
618
- wp_cookie_constants();
619
-
620
- $_COOKIE['wordpress_'.COOKIEHASH] = $auth_cookie;
621
-
622
- }
623
- function mmb_set_logged_in_cookie( $logged_in_cookie ){
624
- if(!defined('MMB_USER_LOGIN'))
625
- return false;
626
-
627
- if( !defined('COOKIEHASH') )
628
- wp_cookie_constants();
629
-
630
- $_COOKIE['wordpress_logged_in_'.COOKIEHASH] = $logged_in_cookie;
631
- }
632
-
633
- function admin_actions(){
634
- add_filter('all_plugins', array($this, 'worker_replace'));
635
- }
636
-
637
- function worker_replace($all_plugins){
638
- $replace = get_option("mwp_worker_brand");
639
- if(is_array($replace)){
640
- if($replace['name'] || $replace['desc'] || $replace['author'] || $replace['author_url']){
641
- $all_plugins['worker/init.php']['Name'] = $replace['name'];
642
- $all_plugins['worker/init.php']['Title'] = $replace['name'];
643
- $all_plugins['worker/init.php']['Description'] = $replace['desc'];
644
- $all_plugins['worker/init.php']['AuthorURI'] = $replace['author_url'];
645
- $all_plugins['worker/init.php']['Author'] = $replace['author'];
646
- $all_plugins['worker/init.php']['AuthorName'] = $replace['author'];
647
- $all_plugins['worker/init.php']['PluginURI'] = '';
648
- }
649
-
650
- if($replace['hide']){
651
- if (!function_exists('get_plugins')) {
652
- include_once(ABSPATH . 'wp-admin/includes/plugin.php');
653
- }
654
- $activated_plugins = get_option('active_plugins');
655
- if (!$activated_plugins)
656
- $activated_plugins = array();
657
- if(in_array('worker/init.php',$activated_plugins))
658
- unset($all_plugins['worker/init.php']);
659
- }
660
- }
661
-
662
-
663
- return $all_plugins;
664
- }
665
-
666
- }
 
 
 
 
667
  ?>
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
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "core.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Core extends MMB_Helper
16
+ {
17
+ var $name;
18
+ var $slug;
19
+ var $settings;
20
+ var $remote_client;
21
+ var $comment_instance;
22
+ var $plugin_instance;
23
+ var $theme_instance;
24
+ var $wp_instance;
25
+ var $post_instance;
26
+ var $stats_instance;
27
+ var $search_instance;
28
+ var $links_instance;
29
+ var $user_instance;
30
+ var $backup_instance;
31
+ var $installer_instance;
32
+ var $mmb_multisite;
33
+ var $network_admin_install;
34
+ private $action_call;
35
+ private $action_params;
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;
56
+ $this->network_admin_install = get_option('mmb_network_admin_install');
57
+ }
58
+ } else if (!empty($wpmu_version)) {
59
+ $this->mmb_multisite = $blog_id;
60
+ $this->network_admin_install = get_option('mmb_network_admin_install');
61
+ } else {
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 ){
69
+ if( is_network_admin() && $this->network_admin_install == '1'){
70
+ add_action('network_admin_notices', array( &$this, 'network_admin_notice' ));
71
+ } else if( $this->network_admin_install != '1' ){
72
+ $parent_key = $this->get_parent_blog_option('_worker_public_key');
73
+ if(empty($parent_key))
74
+ add_action('admin_notices', array( &$this, 'admin_notice' ));
75
+ }
76
+ } else {
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',
95
+ 'remove_site' => 'mmb_remove_site',
96
+ 'backup_clone' => 'mmb_backup_now',
97
+ 'restore' => 'mmb_restore_now',
98
+ 'optimize_tables' => 'mmb_optimize_tables',
99
+ 'check_wp_version' => 'mmb_wp_checkversion',
100
+ 'create_post' => 'mmb_post_create',
101
+ 'update_worker' => 'mmb_update_worker_plugin',
102
+ 'change_comment_status' => 'mmb_change_comment_status',
103
+ 'change_post_status' => 'mmb_change_post_status',
104
+ 'get_comment_stats' => 'mmb_comment_stats_get',
105
+ 'install_addon' => 'mmb_install_addon',
106
+ 'get_links' => 'mmb_get_links',
107
+ 'add_link' => 'mmb_add_link',
108
+ 'delete_link' => 'mmb_delete_link',
109
+ 'delete_links' => 'mmb_delete_links',
110
+ 'get_comments' => 'mmb_get_comments',
111
+ 'action_comment' => 'mmb_action_comment',
112
+ 'bulk_action_comments' => 'mmb_bulk_action_comments',
113
+ 'replyto_comment' => 'mmb_reply_comment',
114
+ 'add_user' => 'mmb_add_user',
115
+ 'email_backup' => 'mmb_email_backup',
116
+ 'check_backup_compat' => 'mmb_check_backup_compat',
117
+ 'scheduled_backup' => 'mmb_scheduled_backup',
118
+ 'run_task' => 'mmb_run_task_now',
119
+ 'execute_php_code' => 'mmb_execute_php_code',
120
+ 'delete_backup' => 'mmm_delete_backup',
121
+ 'remote_backup_now' => 'mmb_remote_backup_now',
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',
129
+ 'edit_posts' => 'mmb_edit_posts',
130
+ 'get_pages' => 'mmb_get_pages',
131
+ 'delete_page' => 'mmb_delete_page',
132
+ 'get_plugins_themes' => 'mmb_get_plugins_themes',
133
+ 'edit_plugins_themes' => 'mmb_edit_plugins_themes',
134
+ 'worker_brand' => 'mmb_worker_brand',
135
+ 'set_alerts' => 'mmb_set_alerts',
136
+ 'maintenance' => 'mmb_maintenance_mode',
137
+ 'get_dbname' => 'mmb_get_dbname'
138
+ );
139
+
140
+ add_action('rightnow_end', array( &$this, 'add_right_now_info' ));
141
+ add_action('admin_init', array(&$this,'admin_actions'));
142
+ add_action('init', array( &$this, 'mmb_remote_action'), 9999);
143
+ add_action('setup_theme', 'mmb_parse_request');
144
+ add_action('set_auth_cookie', array( &$this, 'mmb_set_auth_cookie'));
145
+ add_action('set_logged_in_cookie', array( &$this, 'mmb_set_logged_in_cookie'));
146
+
147
+ }
148
+
149
+ function mmb_remote_action(){
150
+ if($this->action_call != null){
151
+ $params = isset($this->action_params) && $this->action_params != null ? $this->action_params : array();
152
+ call_user_func($this->action_call, $params);
153
+ }
154
+ }
155
+
156
+ function register_action_params( $action = false, $params = array() ){
157
+
158
+ if(isset($this->mmb_pre_init_actions[$action]) && function_exists($this->mmb_pre_init_actions[$action])){
159
+ call_user_func($this->mmb_pre_init_actions[$action], $params);
160
+ }
161
+
162
+ if(isset($this->mmb_init_actions[$action]) && function_exists($this->mmb_init_actions[$action])){
163
+ $this->action_call = $this->mmb_init_actions[$action];
164
+ $this->action_params = $params;
165
+
166
+ if( isset($this->mmb_pre_init_filters[$action]) && !empty($this->mmb_pre_init_filters[$action])){
167
+ global $mmb_filters;
168
+
169
+ foreach($this->mmb_pre_init_filters[$action] as $_name => $_functions){
170
+ if(!empty($_functions)){
171
+ $data = array();
172
+
173
+ foreach($_functions as $_k => $_callback){
174
+ if(is_array($_callback) && method_exists($_callback[0], $_callback[1]) ){
175
+ $data = call_user_func( $_callback, $params );
176
+ } elseif (is_string($_callback) && function_exists( $_callback )){
177
+ $data = call_user_func( $_callback, $params );
178
+ }
179
+ $mmb_filters[$_name] = isset($mmb_filters[$_name]) && !empty($mmb_filters[$_name]) ? array_merge($mmb_filters[$_name], $data) : $data;
180
+ add_filter( $_name, create_function( '$a' , 'global $mmb_filters; return array_merge($a, $mmb_filters["'.$_name.'"]);') );
181
+ }
182
+ }
183
+
184
+ }
185
+ }
186
+ return true;
187
+ }
188
+ return false;
189
+ }
190
+
191
+ /**
192
+ * Add notice to network admin dashboard for security reasons
193
+ *
194
+ */
195
+ function network_admin_notice()
196
+ {
197
+ echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
198
+ 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>.
199
+ </p></div>';
200
+ }
201
+
202
+
203
+ /**
204
+ * Add notice to admin dashboard for security reasons
205
+ *
206
+ */
207
+ function admin_notice()
208
+ {
209
+ echo '<div class="error" style="text-align: center;"><p style="color: red; font-size: 14px; font-weight: bold;">Attention !</p><p>
210
+ 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>.
211
+ </p></div>';
212
+ }
213
+
214
+ /**
215
+ * Add an item into the Right Now Dashboard widget
216
+ * to inform that the blog can be managed remotely
217
+ *
218
+ */
219
+ function add_right_now_info()
220
+ {
221
+ echo '<div class="mmb-slave-info">
222
+ <p>This site can be managed remotely.</p>
223
+ </div>';
224
+ }
225
+
226
+ /**
227
+ * Get parent blog options
228
+ *
229
+ */
230
+ private function get_parent_blog_option( $option_name = '' )
231
+ {
232
+ global $wpdb;
233
+ $option = $wpdb->get_var( $wpdb->prepare( "SELECT `option_value` FROM {$wpdb->base_prefix}options WHERE option_name = '{$option_name}' LIMIT 1" ) );
234
+ return $option;
235
+ }
236
+
237
+ /**
238
+ * Gets an instance of the Comment class
239
+ *
240
+ */
241
+ function get_comment_instance()
242
+ {
243
+ if (!isset($this->comment_instance)) {
244
+ $this->comment_instance = new MMB_Comment();
245
+ }
246
+
247
+ return $this->comment_instance;
248
+ }
249
+
250
+ /**
251
+ * Gets an instance of the Plugin class
252
+ *
253
+ */
254
+ function get_plugin_instance()
255
+ {
256
+ if (!isset($this->plugin_instance)) {
257
+ $this->plugin_instance = new MMB_Plugin();
258
+ }
259
+
260
+ return $this->plugin_instance;
261
+ }
262
+
263
+ /**
264
+ * Gets an instance of the Theme class
265
+ *
266
+ */
267
+ function get_theme_instance()
268
+ {
269
+ if (!isset($this->theme_instance)) {
270
+ $this->theme_instance = new MMB_Theme();
271
+ }
272
+
273
+ return $this->theme_instance;
274
+ }
275
+
276
+
277
+ /**
278
+ * Gets an instance of MMB_Post class
279
+ *
280
+ */
281
+ function get_post_instance()
282
+ {
283
+ if (!isset($this->post_instance)) {
284
+ $this->post_instance = new MMB_Post();
285
+ }
286
+
287
+ return $this->post_instance;
288
+ }
289
+
290
+ /**
291
+ * Gets an instance of Blogroll class
292
+ *
293
+ */
294
+ function get_blogroll_instance()
295
+ {
296
+ if (!isset($this->blogroll_instance)) {
297
+ $this->blogroll_instance = new MMB_Blogroll();
298
+ }
299
+
300
+ return $this->blogroll_instance;
301
+ }
302
+
303
+
304
+
305
+ /**
306
+ * Gets an instance of the WP class
307
+ *
308
+ */
309
+ function get_wp_instance()
310
+ {
311
+ if (!isset($this->wp_instance)) {
312
+ $this->wp_instance = new MMB_WP();
313
+ }
314
+
315
+ return $this->wp_instance;
316
+ }
317
+
318
+ /**
319
+ * Gets an instance of User
320
+ *
321
+ */
322
+ function get_user_instance()
323
+ {
324
+ if (!isset($this->user_instance)) {
325
+ $this->user_instance = new MMB_User();
326
+ }
327
+
328
+ return $this->user_instance;
329
+ }
330
+
331
+ /**
332
+ * Gets an instance of stats class
333
+ *
334
+ */
335
+ function get_stats_instance()
336
+ {
337
+ if (!isset($this->stats_instance)) {
338
+ $this->stats_instance = new MMB_Stats();
339
+ }
340
+ return $this->stats_instance;
341
+ }
342
+ /**
343
+ * Gets an instance of search class
344
+ *
345
+ */
346
+ function get_search_instance()
347
+ {
348
+ if (!isset($this->search_instance)) {
349
+ $this->search_instance = new MMB_Search();
350
+ }
351
+ //return $this->search_instance;
352
+ return $this->search_instance;
353
+ }
354
+ /**
355
+ * Gets an instance of stats class
356
+ *
357
+ */
358
+ function get_backup_instance()
359
+ {
360
+ if (!isset($this->backup_instance)) {
361
+ $this->backup_instance = new MMB_Backup();
362
+ }
363
+
364
+ return $this->backup_instance;
365
+ }
366
+
367
+ /**
368
+ * Gets an instance of links class
369
+ *
370
+ */
371
+ function get_link_instance()
372
+ {
373
+ if (!isset($this->link_instance)) {
374
+ $this->link_instance = new MMB_Link();
375
+ }
376
+
377
+ return $this->link_instance;
378
+ }
379
+
380
+ function get_installer_instance()
381
+ {
382
+ if (!isset($this->installer_instance)) {
383
+ $this->installer_instance = new MMB_Installer();
384
+ }
385
+ return $this->installer_instance;
386
+ }
387
+
388
+ /**
389
+ * Plugin install callback function
390
+ * Check PHP version
391
+ */
392
+ function install() {
393
+
394
+ global $wpdb, $_wp_using_ext_object_cache, $current_user;
395
+ $_wp_using_ext_object_cache = false;
396
+
397
+ //delete plugin options, just in case
398
+ if ($this->mmb_multisite != false) {
399
+ $network_blogs = $wpdb->get_results($wpdb->prepare("select `blog_id`, `site_id` from `{$wpdb->blogs}`"));
400
+ if(!empty($network_blogs)){
401
+ if( is_network_admin() ){
402
+ update_option('mmb_network_admin_install', 1);
403
+ foreach($network_blogs as $details){
404
+ if($details->site_id == $details->blog_id)
405
+ update_blog_option($details->blog_id, 'mmb_network_admin_install', 1);
406
+ else
407
+ update_blog_option($details->blog_id, 'mmb_network_admin_install', -1);
408
+
409
+ delete_blog_option($blog_id, '_worker_nossl_key');
410
+ delete_blog_option($blog_id, '_worker_public_key');
411
+ delete_blog_option($blog_id, '_action_message_id');
412
+ }
413
+ } else {
414
+ update_option('mmb_network_admin_install', -1);
415
+ delete_option('_worker_nossl_key');
416
+ delete_option('_worker_public_key');
417
+ delete_option('_action_message_id');
418
+ }
419
+ }
420
+ } else {
421
+ delete_option('_worker_nossl_key');
422
+ delete_option('_worker_public_key');
423
+ delete_option('_action_message_id');
424
+ }
425
+
426
+ delete_option('mwp_backup_tasks');
427
+ delete_option('mwp_notifications');
428
+ delete_option('mwp_worker_brand');
429
+ delete_option('mwp_pageview_alerts');
430
+ }
431
+
432
+ /**
433
+ * Saves the (modified) options into the database
434
+ *
435
+ */
436
+ function save_options( $options = array() ){
437
+ global $_mmb_options;
438
+
439
+ $_mmb_options = array_merge( $_mmb_options, $options );
440
+ update_option('wrksettings', $options);
441
+ }
442
+
443
+ /**
444
+ * Deletes options for communication with master
445
+ *
446
+ */
447
+ function uninstall( $deactivate = false )
448
+ {
449
+ global $current_user, $wpdb, $_wp_using_ext_object_cache;
450
+ $_wp_using_ext_object_cache = false;
451
+
452
+ if ($this->mmb_multisite != false) {
453
+ $network_blogs = $wpdb->get_col($wpdb->prepare("select `blog_id` from `{$wpdb->blogs}`"));
454
+ if(!empty($network_blogs)){
455
+ if( is_network_admin() ){
456
+ if( $deactivate ) {
457
+ delete_option('mmb_network_admin_install');
458
+ foreach($network_blogs as $blog_id){
459
+ delete_blog_option($blog_id, 'mmb_network_admin_install');
460
+ delete_blog_option($blog_id, '_worker_nossl_key');
461
+ delete_blog_option($blog_id, '_worker_public_key');
462
+ delete_blog_option($blog_id, '_action_message_id');
463
+ delete_blog_option($blog_id, 'mwp_maintenace_mode');
464
+ delete_blog_option($blog_id, 'mwp_backup_tasks');
465
+ delete_blog_option($blog_id, 'mwp_notifications');
466
+ delete_blog_option($blog_id, 'mwp_worker_brand');
467
+ delete_blog_option($blog_id, 'mwp_pageview_alerts');
468
+ delete_blog_option($blog_id, 'mwp_pageview_alerts');
469
+ }
470
+ }
471
+ } else {
472
+ if( $deactivate )
473
+ delete_option('mmb_network_admin_install');
474
+
475
+ delete_option('_worker_nossl_key');
476
+ delete_option('_worker_public_key');
477
+ delete_option('_action_message_id');
478
+ }
479
+ }
480
+ } else {
481
+ delete_option('_worker_nossl_key');
482
+ delete_option('_worker_public_key');
483
+ delete_option('_action_message_id');
484
+ }
485
+
486
+ //Delete options
487
+ delete_option('mwp_maintenace_mode');
488
+ delete_option('mwp_backup_tasks');
489
+ delete_option('mwp_notifications');
490
+ delete_option('mwp_worker_brand');
491
+ delete_option('mwp_pageview_alerts');
492
+ wp_clear_scheduled_hook('mwp_backup_tasks');
493
+ wp_clear_scheduled_hook('mwp_notifications');
494
+ wp_clear_scheduled_hook('mwp_datasend');
495
+ }
496
+
497
+
498
+ /**
499
+ * Constructs a url (for ajax purpose)
500
+ *
501
+ * @param mixed $base_page
502
+ */
503
+ function construct_url($params = array(), $base_page = 'index.php')
504
+ {
505
+ $url = "$base_page?_wpnonce=" . wp_create_nonce($this->slug);
506
+ foreach ($params as $key => $value) {
507
+ $url .= "&$key=$value";
508
+ }
509
+
510
+ return $url;
511
+ }
512
+
513
+ /**
514
+ * Worker update
515
+ *
516
+ */
517
+ function update_worker_plugin($params)
518
+ {
519
+ extract($params);
520
+ if ($download_url) {
521
+ @include_once ABSPATH . 'wp-admin/includes/file.php';
522
+ @include_once ABSPATH . 'wp-admin/includes/misc.php';
523
+ @include_once ABSPATH . 'wp-admin/includes/template.php';
524
+ @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
525
+ @include_once ABSPATH . 'wp-admin/includes/screen.php';
526
+
527
+ if (!$this->is_server_writable()) {
528
+ return array(
529
+ '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>'
530
+ );
531
+ }
532
+
533
+ ob_start();
534
+ @unlink(dirname(__FILE__));
535
+ $upgrader = new Plugin_Upgrader();
536
+ $result = $upgrader->run(array(
537
+ 'package' => $download_url,
538
+ 'destination' => WP_PLUGIN_DIR,
539
+ 'clear_destination' => true,
540
+ 'clear_working' => true,
541
+ 'hook_extra' => array(
542
+ 'plugin' => 'worker/init.php'
543
+ )
544
+ ));
545
+ ob_end_clean();
546
+ if (is_wp_error($result) || !$result) {
547
+ return array(
548
+ 'error' => 'ManageWP Worker plugin could not be updated.'
549
+ );
550
+ } else {
551
+ return array(
552
+ 'success' => 'ManageWP Worker plugin successfully updated.'
553
+ );
554
+ }
555
+ }
556
+ return array(
557
+ 'error' => 'Bad download path for worker installation file.'
558
+ );
559
+ }
560
+
561
+ /**
562
+ * Automatically logs in when called from Master
563
+ *
564
+ */
565
+ function automatic_login()
566
+ {
567
+ $where = isset($_GET['mwp_goto']) ? $_GET['mwp_goto'] : false;
568
+ $username = isset($_GET['username']) ? $_GET['username'] : '';
569
+ $auto_login = isset($_GET['auto_login']) ? $_GET['auto_login'] : 0;
570
+
571
+ if( !function_exists('is_user_logged_in') )
572
+ include_once( ABSPATH.'wp-includes/pluggable.php' );
573
+
574
+ if (( $auto_login && strlen(trim($username)) && !is_user_logged_in() ) || (isset($this->mmb_multisite) && $this->mmb_multisite )) {
575
+ $signature = base64_decode($_GET['signature']);
576
+ $message_id = trim($_GET['message_id']);
577
+
578
+ $auth = $this->authenticate_message($where . $message_id, $signature, $message_id);
579
+ if ($auth === true) {
580
+
581
+ if (!headers_sent())
582
+ header('P3P: CP="CAO PSA OUR"');
583
+
584
+ if(!defined('MMB_USER_LOGIN'))
585
+ define('MMB_USER_LOGIN', true);
586
+
587
+ $siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
588
+ $user = $this->mmb_get_user_info($username);
589
+ wp_set_current_user($user->ID);
590
+
591
+ if(!defined('COOKIEHASH') || (isset($this->mmb_multisite) && $this->mmb_multisite) )
592
+ wp_cookie_constants();
593
+
594
+ wp_set_auth_cookie($user->ID);
595
+ @mmb_worker_header();
596
+
597
+ if((isset($this->mmb_multisite) && $this->mmb_multisite ) || isset($_REQUEST['mwpredirect'])){
598
+ if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
599
+ wp_safe_redirect(admin_url($where));
600
+ exit();
601
+ }
602
+ }
603
+ } else {
604
+ wp_die($auth['error']);
605
+ }
606
+ } elseif( is_user_logged_in() ) {
607
+ @mmb_worker_header();
608
+ if(isset($_REQUEST['mwpredirect'])){
609
+ if(function_exists('wp_safe_redirect') && function_exists('admin_url')){
610
+ wp_safe_redirect(admin_url($where));
611
+ exit();
612
+ }
613
+ }
614
+ }
615
+ }
616
+
617
+ function mmb_set_auth_cookie( $auth_cookie ){
618
+ if(!defined('MMB_USER_LOGIN'))
619
+ return false;
620
+
621
+ if( !defined('COOKIEHASH') )
622
+ wp_cookie_constants();
623
+
624
+ $_COOKIE['wordpress_'.COOKIEHASH] = $auth_cookie;
625
+
626
+ }
627
+ function mmb_set_logged_in_cookie( $logged_in_cookie ){
628
+ if(!defined('MMB_USER_LOGIN'))
629
+ return false;
630
+
631
+ if( !defined('COOKIEHASH') )
632
+ wp_cookie_constants();
633
+
634
+ $_COOKIE['wordpress_logged_in_'.COOKIEHASH] = $logged_in_cookie;
635
+ }
636
+
637
+ function admin_actions(){
638
+ add_filter('all_plugins', array($this, 'worker_replace'));
639
+ }
640
+
641
+ function worker_replace($all_plugins){
642
+ $replace = get_option("mwp_worker_brand");
643
+ if(is_array($replace)){
644
+ if($replace['name'] || $replace['desc'] || $replace['author'] || $replace['author_url']){
645
+ $all_plugins['worker/init.php']['Name'] = $replace['name'];
646
+ $all_plugins['worker/init.php']['Title'] = $replace['name'];
647
+ $all_plugins['worker/init.php']['Description'] = $replace['desc'];
648
+ $all_plugins['worker/init.php']['AuthorURI'] = $replace['author_url'];
649
+ $all_plugins['worker/init.php']['Author'] = $replace['author'];
650
+ $all_plugins['worker/init.php']['AuthorName'] = $replace['author'];
651
+ $all_plugins['worker/init.php']['PluginURI'] = '';
652
+ }
653
+
654
+ if($replace['hide']){
655
+ if (!function_exists('get_plugins')) {
656
+ include_once(ABSPATH . 'wp-admin/includes/plugin.php');
657
+ }
658
+ $activated_plugins = get_option('active_plugins');
659
+ if (!$activated_plugins)
660
+ $activated_plugins = array();
661
+ if(in_array('worker/init.php',$activated_plugins))
662
+ unset($all_plugins['worker/init.php']);
663
+ }
664
+ }
665
+
666
+
667
+ return $all_plugins;
668
+ }
669
+
670
+ }
671
  ?>
helper.class.php CHANGED
@@ -1,545 +1,545 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * helper.class.php
5
- *
6
- * Utility functions
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
-
13
- define('MWP_SHOW_LOG', false);
14
-
15
- class MMB_Helper
16
- {
17
- /**
18
- * A helper function to log data
19
- *
20
- * @param mixed $mixed
21
- */
22
- function _log($mixed)
23
- {
24
- if(defined('MWP_SHOW_LOG') && MWP_SHOW_LOG == true){
25
- if (is_array($mixed)) {
26
- $mixed = print_r($mixed, 1);
27
- } else if (is_object($mixed)) {
28
- ob_start();
29
- var_dump($mixed);
30
- $mixed = ob_get_clean();
31
- }
32
-
33
- $handle = fopen(dirname(__FILE__) . '/log', 'a');
34
- fwrite($handle, $mixed . PHP_EOL);
35
- fclose($handle);
36
- }
37
- }
38
-
39
- function _escape(&$array)
40
- {
41
- global $wpdb;
42
-
43
- if (!is_array($array)) {
44
- return ($wpdb->escape($array));
45
- } else {
46
- foreach ((array) $array as $k => $v) {
47
- if (is_array($v)) {
48
- $this->_escape($array[$k]);
49
- } else if (is_object($v)) {
50
- //skip
51
- } else {
52
- $array[$k] = $wpdb->escape($v);
53
- }
54
- }
55
- }
56
- }
57
-
58
- /**
59
- * Initializes the file system
60
- *
61
- */
62
- function init_filesystem()
63
- {
64
- global $wp_filesystem;
65
-
66
- if (!$wp_filesystem || !is_object($wp_filesystem)) {
67
- WP_Filesystem();
68
- }
69
-
70
- if (!is_object($wp_filesystem))
71
- return FALSE;
72
-
73
- return TRUE;
74
- }
75
-
76
- /**
77
- *
78
- * Check if function exists or not on `suhosin` black list
79
- *
80
- */
81
-
82
- function mmb_get_user_info( $user_info = false, $info = 'login' ){
83
-
84
- if($user_info === false)
85
- return false;
86
-
87
- if( strlen( trim( $user_info ) ) == 0)
88
- return false;
89
-
90
-
91
- global $wp_version;
92
- if (version_compare($wp_version, '3.2.2', '<=')){
93
- return get_userdatabylogin( $user_info );
94
- } else {
95
- return get_user_by( $info, $user_info );
96
- }
97
- }
98
-
99
- /**
100
- *
101
- * Call action item filters
102
- *
103
- */
104
-
105
- function mmb_parse_action_params( $key = '', $params = null, $call_object = null ){
106
-
107
- global $_mmb_item_filter;
108
- $call_object = $call_object !== null ? $call_object : $this;
109
- $return = array();
110
-
111
- if(isset($_mmb_item_filter[$key]) && !empty($_mmb_item_filter[$key])){
112
- if( isset($params['item_filter']) && !empty($params['item_filter'])){
113
- foreach($params['item_filter'] as $_items){
114
- if(!empty($_items)){
115
- foreach($_items as $_item){
116
- if(in_array($_item[0], $_mmb_item_filter[$key])){
117
- $_item[1] = isset($_item[1]) ? $_item[1] : array();
118
- $return = call_user_func(array( &$call_object, 'get_'.$_item[0]), $return, $_item[1]);
119
- }
120
- }
121
- }
122
- }
123
- }
124
- }
125
-
126
- return $return;
127
- }
128
-
129
- /**
130
- *
131
- * Check if function exists or not on `suhosin` black list
132
- *
133
- */
134
-
135
- function mmb_function_exists($function_callback){
136
-
137
- if(!function_exists($function_callback))
138
- return false;
139
-
140
- $disabled = explode(', ', @ini_get('disable_functions'));
141
- if (in_array($function_callback, $disabled))
142
- return false;
143
-
144
- if (extension_loaded('suhosin')) {
145
- $suhosin = @ini_get("suhosin.executor.func.blacklist");
146
- if (empty($suhosin) == false) {
147
- $suhosin = explode(',', $suhosin);
148
- $blacklist = array_map('trim', $suhosin);
149
- $blacklist = array_map('strtolower', $blacklist);
150
- if(in_array($function_callback, $blacklist))
151
- return false;
152
- }
153
- }
154
- return true;
155
- }
156
-
157
- /**
158
- * Gets transient based on WP version
159
- *
160
- * @global string $wp_version
161
- * @param string $option_name
162
- * @return mixed
163
- */
164
-
165
- function mmb_set_transient($option_name = false, $data = false){
166
-
167
- if (!$option_name || !$data) {
168
- return false;
169
- }
170
- if($this->mmb_multisite)
171
- return $this->mmb_set_sitemeta_transient($option_name, $data);
172
-
173
- global $wp_version;
174
-
175
- if (version_compare($wp_version, '2.7.9', '<=')) {
176
- update_option($option_name, $data);
177
- } else if (version_compare($wp_version, '2.9.9', '<=')) {
178
- update_option('_transient_' . $option_name, $data);
179
- } else {
180
- update_option('_site_transient_' . $option_name, $data);
181
- }
182
-
183
- }
184
- function mmb_get_transient($option_name)
185
- {
186
- if (trim($option_name) == '') {
187
- return FALSE;
188
- }
189
- if($this->mmb_multisite)
190
- return $this->mmb_get_sitemeta_transient($option_name);
191
-
192
- global $wp_version;
193
-
194
- $transient = array();
195
-
196
- if (version_compare($wp_version, '2.7.9', '<=')) {
197
- return get_option($option_name);
198
- } else if (version_compare($wp_version, '2.9.9', '<=')) {
199
- $transient = get_option('_transient_' . $option_name);
200
- return apply_filters("transient_".$option_name, $transient);
201
- } else {
202
- $transient = get_option('_site_transient_' . $option_name);
203
- return apply_filters("site_transient_".$option_name, $transient);
204
- }
205
- }
206
-
207
- function mmb_delete_transient($option_name)
208
- {
209
- if (trim($option_name) == '') {
210
- return FALSE;
211
- }
212
-
213
- global $wp_version;
214
-
215
- if (version_compare($wp_version, '2.7.9', '<=')) {
216
- delete_option($option_name);
217
- } else if (version_compare($wp_version, '2.9.9', '<=')) {
218
- delete_option('_transient_' . $option_name);
219
- } else {
220
- delete_option('_site_transient_' . $option_name);
221
- }
222
- }
223
-
224
- function mmb_get_sitemeta_transient($option_name){
225
- global $wpdb;
226
- $option_name = '_site_transient_'. $option_name;
227
-
228
- $result = $wpdb->get_var( $wpdb->prepare("SELECT `meta_value` FROM `{$wpdb->sitemeta}` WHERE meta_key = '{$option_name}' AND `site_id` = '{$this->mmb_multisite}' "));
229
- $result = maybe_unserialize($result);
230
- return $result;
231
- }
232
-
233
- function mmb_set_sitemeta_transient($option_name, $option_value){
234
- global $wpdb;
235
- $option_name = '_site_transient_'. $option_name;
236
-
237
- if($this->mmb_get_sitemeta_transient($option_name)){
238
- $result = $wpdb->update( $wpdb->sitemeta,
239
- array(
240
- 'meta_value' => maybe_serialize($option_value)
241
- ),
242
- array(
243
- 'meta_key' => $option_name,
244
- 'site_id' => $this->mmb_multisite
245
- )
246
- );
247
- }else {
248
- $result = $wpdb->insert( $wpdb->sitemeta,
249
- array(
250
- 'meta_key' => $option_name,
251
- 'meta_value' => maybe_serialize($option_value),
252
- 'site_id' => $this->mmb_multisite
253
- )
254
- );
255
- }
256
- return $result;
257
- }
258
-
259
- function delete_temp_dir($directory)
260
- {
261
- if (substr($directory, -1) == "/") {
262
- $directory = substr($directory, 0, -1);
263
- }
264
- if (!file_exists($directory) || !is_dir($directory)) {
265
- return false;
266
- } elseif (!is_readable($directory)) {
267
- return false;
268
- } else {
269
- $directoryHandle = opendir($directory);
270
-
271
- while ($contents = readdir($directoryHandle)) {
272
- if ($contents != '.' && $contents != '..') {
273
- $path = $directory . "/" . $contents;
274
-
275
- if (is_dir($path)) {
276
- $this->delete_temp_dir($path);
277
- } else {
278
- unlink($path);
279
- }
280
- }
281
- }
282
- closedir($directoryHandle);
283
- rmdir($directory);
284
- return true;
285
- }
286
- }
287
-
288
- function set_worker_message_id($message_id = false)
289
- {
290
- if ($message_id) {
291
- add_option('_action_message_id', $message_id) or update_option('_action_message_id', $message_id);
292
- return $message_id;
293
- }
294
- return false;
295
- }
296
-
297
- function get_worker_message_id()
298
- {
299
- return (int) get_option('_action_message_id');
300
- }
301
-
302
- function set_master_public_key($public_key = false)
303
- {
304
- if ($public_key && !get_option('_worker_public_key')) {
305
- add_option('_worker_public_key', base64_encode($public_key));
306
- return true;
307
- }
308
- return false;
309
- }
310
-
311
- function get_master_public_key()
312
- {
313
- if (!get_option('_worker_public_key'))
314
- return false;
315
- return base64_decode(get_option('_worker_public_key'));
316
- }
317
-
318
-
319
- function get_random_signature()
320
- {
321
- if (!get_option('_worker_nossl_key'))
322
- return false;
323
- return base64_decode(get_option('_worker_nossl_key'));
324
- }
325
-
326
- function set_random_signature($random_key = false)
327
- {
328
- if ($random_key && !get_option('_worker_nossl_key')) {
329
- add_option('_worker_nossl_key', base64_encode($random_key));
330
- return true;
331
- }
332
- return false;
333
- }
334
-
335
-
336
- function authenticate_message($data = false, $signature = false, $message_id = false)
337
- {
338
- if (!$data && !$signature) {
339
- return array(
340
- 'error' => 'Authentication failed.'
341
- );
342
- }
343
-
344
- $current_message = $this->get_worker_message_id();
345
-
346
- if ((int) $current_message >= (int) $message_id)
347
- return array(
348
- 'error' => 'Invalid message recieved. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
349
- );
350
-
351
- $pl_key = $this->get_master_public_key();
352
- if (!$pl_key) {
353
- return array(
354
- 'error' => 'Authentication failed. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
355
- );
356
- }
357
-
358
- if (function_exists('openssl_verify') && !$this->get_random_signature()) {
359
- $verify = openssl_verify($data, $signature, $pl_key);
360
- if ($verify == 1) {
361
- $message_id = $this->set_worker_message_id($message_id);
362
- return true;
363
- } else if ($verify == 0) {
364
- return array(
365
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
366
- );
367
- } else {
368
- return array(
369
- 'error' => 'Command not successful! Please try again.'
370
- );
371
- }
372
- } else if ($this->get_random_signature()) {
373
- if (md5($data . $this->get_random_signature()) == $signature) {
374
- $message_id = $this->set_worker_message_id($message_id);
375
- return true;
376
- }
377
- return array(
378
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
379
- );
380
- }
381
- // no rand key - deleted in get_stat maybe
382
- else
383
- return array(
384
- 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
385
- );
386
- }
387
-
388
- function get_secure_hash(){
389
-
390
- $pl_key = $this->get_master_public_key();
391
- if ( empty($pl_key) )
392
- $pl_key = $this->get_random_signature();
393
-
394
- if( !empty($pl_key) )
395
- return md5(base64_encode($pl_key));
396
-
397
- return false;
398
- }
399
-
400
- function _secure_data($data = false){
401
- if($data == false)
402
- return false;
403
-
404
- $pl_key = $this->get_master_public_key();
405
- if (!$pl_key)
406
- return false;
407
-
408
- $secure = '';
409
- if( function_exists('openssl_public_decrypt') && !$this->get_random_signature() ){
410
- if(is_array($data) && !empty($data)){
411
- foreach($data as $input){
412
- openssl_public_decrypt($input, $decrypted, $pl_key);
413
- $secure .= $decrypted;
414
- }
415
- } else if ( is_string( $data ) ) {
416
- openssl_public_decrypt($data, $decrypted, $pl_key);
417
- $secure = $decrypted;
418
- } else {
419
- $secure = $data;
420
- }
421
- return $secure;
422
- }
423
- return false;
424
-
425
- }
426
-
427
- function encrypt_data( $data = false, $single = false ){
428
- if( empty($data) )
429
- return $data;
430
-
431
- $pl_key = $this->get_master_public_key();
432
- if ( !$pl_key )
433
- return false;
434
-
435
- $data = serialize( $data );
436
- $crypted = '';
437
- if( function_exists('openssl_public_encrypt') && !$this->get_random_signature() ){
438
- $length = strlen( $data );
439
- if( $length > 100 ){
440
- for($i = 0; $i <= $length + 100; $i = $i+100){
441
- $input = substr($data, $i, 100);
442
- openssl_public_encrypt($input, $crypt, $pl_key);
443
- $crypted .= base64_encode($crypt).'::';
444
- }
445
- } else
446
- openssl_public_encrypt($input, $crypted, $pl_key);
447
- } else {
448
- $crypted = base64_encode($data);
449
- }
450
-
451
- return $crypted;
452
-
453
- }
454
-
455
- function check_if_user_exists($username = false)
456
- {
457
- global $wpdb;
458
- if ($username) {
459
- if( !function_exists('username_exists') )
460
- include_once(ABSPATH . WPINC . '/registration.php');
461
-
462
- include_once(ABSPATH . 'wp-includes/pluggable.php');
463
-
464
- if (username_exists($username) == null) {
465
- return false;
466
- }
467
-
468
- $user = (array) $this->mmb_get_user_info( $username );
469
- if ((isset($user[$wpdb->prefix . 'user_level']) && $user[$wpdb->prefix . 'user_level'] == 10) || isset($user[$wpdb->prefix . 'capabilities']['administrator']) ||
470
- (isset($user['caps']['administrator']) && $user['caps']['administrator'] == 1)){
471
- return true;
472
- }
473
- return false;
474
- }
475
- return false;
476
- }
477
-
478
- function refresh_updates()
479
- {
480
- if (rand(1, 3) == '2') {
481
- require_once(ABSPATH . WPINC . '/update.php');
482
- wp_update_plugins();
483
- wp_update_themes();
484
- wp_version_check();
485
- }
486
- }
487
-
488
- function remove_http($url = '')
489
- {
490
- if ($url == 'http://' OR $url == 'https://') {
491
- return $url;
492
- }
493
- return preg_replace('/^(http|https)\:\/\/(www.)?/i', '', $url);
494
-
495
- }
496
-
497
- function mmb_get_error($error_object)
498
- {
499
- if (!is_wp_error($error_object)) {
500
- return $error_object != '' ? $error_object : '';
501
- } else {
502
- $errors = array();
503
- if(!empty($error_object->error_data)) {
504
- foreach ($error_object->error_data as $error_key => $error_string) {
505
- $errors[] = str_replace('_', ' ', ucfirst($error_key)) . ': ' . $error_string;
506
- }
507
- } elseif (!empty($error_object->errors)){
508
- foreach ($error_object->errors as $error_key => $err) {
509
- $errors[] = 'Error: '.str_replace('_', ' ', strtolower($error_key));
510
- }
511
- }
512
- return implode('<br />', $errors);
513
- }
514
- }
515
-
516
- function is_server_writable(){
517
- if((!defined('FTP_HOST') || !defined('FTP_USER') || !defined('FTP_PASS')) && (get_filesystem_method(array(), false) != 'direct'))
518
- return false;
519
- else
520
- return true;
521
- }
522
-
523
- function mmb_download_url($url, $file_name)
524
- {
525
- if (function_exists('fopen') && function_exists('ini_get') && ini_get('allow_url_fopen') == true && ($destination = @fopen($file_name, 'wb')) && ($source = @fopen($url, "r")) ) {
526
-
527
-
528
- while ($a = @fread($source, 1024* 1024)) {
529
- @fwrite($destination, $a);
530
- }
531
-
532
- fclose($source);
533
- fclose($destination);
534
- } else
535
- if (!fsockopen_download($url, $file_name))
536
- die('Error downloading file ' . $url);
537
- return $file_name;
538
- }
539
-
540
-
541
-
542
-
543
-
544
- }
545
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * helper.class.php
5
+ *
6
+ * Utility functions
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+
13
+ define('MWP_SHOW_LOG', false);
14
+
15
+ class MMB_Helper
16
+ {
17
+ /**
18
+ * A helper function to log data
19
+ *
20
+ * @param mixed $mixed
21
+ */
22
+ function _log($mixed)
23
+ {
24
+ if(defined('MWP_SHOW_LOG') && MWP_SHOW_LOG == true){
25
+ if (is_array($mixed)) {
26
+ $mixed = print_r($mixed, 1);
27
+ } else if (is_object($mixed)) {
28
+ ob_start();
29
+ var_dump($mixed);
30
+ $mixed = ob_get_clean();
31
+ }
32
+
33
+ $md5 = get_option('mwp_log_md5');
34
+ if ($md5 === false) {
35
+ $md5 = md5(date('jS F Y h:i:s A'));
36
+ update_option('mwp_log_md5', $md5);
37
+ }
38
+ $handle = fopen(dirname(__FILE__) . '/log_'.$md5, 'a');
39
+ fwrite($handle, $mixed . PHP_EOL);
40
+ fclose($handle);
41
+ }
42
+ }
43
+
44
+ function _escape(&$array)
45
+ {
46
+ global $wpdb;
47
+
48
+ if (!is_array($array)) {
49
+ return ($wpdb->escape($array));
50
+ } else {
51
+ foreach ((array) $array as $k => $v) {
52
+ if (is_array($v)) {
53
+ $this->_escape($array[$k]);
54
+ } else if (is_object($v)) {
55
+ //skip
56
+ } else {
57
+ $array[$k] = $wpdb->escape($v);
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Initializes the file system
65
+ *
66
+ */
67
+ function init_filesystem()
68
+ {
69
+ global $wp_filesystem;
70
+
71
+ if (!$wp_filesystem || !is_object($wp_filesystem)) {
72
+ WP_Filesystem();
73
+ }
74
+
75
+ if (!is_object($wp_filesystem))
76
+ return FALSE;
77
+
78
+ return TRUE;
79
+ }
80
+
81
+ /**
82
+ *
83
+ * Check if function exists or not on `suhosin` black list
84
+ *
85
+ */
86
+
87
+ function mmb_get_user_info( $user_info = false, $info = 'login' ){
88
+
89
+ if($user_info === false)
90
+ return false;
91
+
92
+ if( strlen( trim( $user_info ) ) == 0)
93
+ return false;
94
+
95
+
96
+ global $wp_version;
97
+ if (version_compare($wp_version, '3.2.2', '<=')){
98
+ return get_userdatabylogin( $user_info );
99
+ } else {
100
+ return get_user_by( $info, $user_info );
101
+ }
102
+ }
103
+
104
+ /**
105
+ *
106
+ * Call action item filters
107
+ *
108
+ */
109
+
110
+ function mmb_parse_action_params( $key = '', $params = null, $call_object = null ){
111
+
112
+ global $_mmb_item_filter;
113
+ $call_object = $call_object !== null ? $call_object : $this;
114
+ $return = array();
115
+
116
+ if(isset($_mmb_item_filter[$key]) && !empty($_mmb_item_filter[$key])){
117
+ if( isset($params['item_filter']) && !empty($params['item_filter'])){
118
+ foreach($params['item_filter'] as $_items){
119
+ if(!empty($_items)){
120
+ foreach($_items as $_item){
121
+ if(in_array($_item[0], $_mmb_item_filter[$key])){
122
+ $_item[1] = isset($_item[1]) ? $_item[1] : array();
123
+ $return = call_user_func(array( &$call_object, 'get_'.$_item[0]), $return, $_item[1]);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ return $return;
132
+ }
133
+
134
+ /**
135
+ *
136
+ * Check if function exists or not on `suhosin` black list
137
+ *
138
+ */
139
+
140
+ function mmb_function_exists($function_callback){
141
+
142
+ if(!function_exists($function_callback))
143
+ return false;
144
+
145
+ $disabled = explode(', ', @ini_get('disable_functions'));
146
+ if (in_array($function_callback, $disabled))
147
+ return false;
148
+
149
+ if (extension_loaded('suhosin')) {
150
+ $suhosin = @ini_get("suhosin.executor.func.blacklist");
151
+ if (empty($suhosin) == false) {
152
+ $suhosin = explode(',', $suhosin);
153
+ $blacklist = array_map('trim', $suhosin);
154
+ $blacklist = array_map('strtolower', $blacklist);
155
+ if(in_array($function_callback, $blacklist))
156
+ return false;
157
+ }
158
+ }
159
+ return true;
160
+ }
161
+
162
+ /**
163
+ * Gets transient based on WP version
164
+ *
165
+ * @global string $wp_version
166
+ * @param string $option_name
167
+ * @return mixed
168
+ */
169
+
170
+ function mmb_set_transient($option_name = false, $data = false){
171
+
172
+ if (!$option_name || !$data) {
173
+ return false;
174
+ }
175
+ if($this->mmb_multisite)
176
+ return $this->mmb_set_sitemeta_transient($option_name, $data);
177
+
178
+ global $wp_version;
179
+
180
+ if (version_compare($wp_version, '2.7.9', '<=')) {
181
+ update_option($option_name, $data);
182
+ } else if (version_compare($wp_version, '2.9.9', '<=')) {
183
+ update_option('_transient_' . $option_name, $data);
184
+ } else {
185
+ update_option('_site_transient_' . $option_name, $data);
186
+ }
187
+
188
+ }
189
+ function mmb_get_transient($option_name)
190
+ {
191
+ if (trim($option_name) == '') {
192
+ return FALSE;
193
+ }
194
+ if($this->mmb_multisite)
195
+ return $this->mmb_get_sitemeta_transient($option_name);
196
+
197
+ global $wp_version;
198
+
199
+ $transient = array();
200
+
201
+ if (version_compare($wp_version, '2.7.9', '<=')) {
202
+ return get_option($option_name);
203
+ } else if (version_compare($wp_version, '2.9.9', '<=')) {
204
+ $transient = get_option('_transient_' . $option_name);
205
+ return apply_filters("transient_".$option_name, $transient);
206
+ } else {
207
+ $transient = get_option('_site_transient_' . $option_name);
208
+ return apply_filters("site_transient_".$option_name, $transient);
209
+ }
210
+ }
211
+
212
+ function mmb_delete_transient($option_name)
213
+ {
214
+ if (trim($option_name) == '') {
215
+ return FALSE;
216
+ }
217
+
218
+ global $wp_version;
219
+
220
+ if (version_compare($wp_version, '2.7.9', '<=')) {
221
+ delete_option($option_name);
222
+ } else if (version_compare($wp_version, '2.9.9', '<=')) {
223
+ delete_option('_transient_' . $option_name);
224
+ } else {
225
+ delete_option('_site_transient_' . $option_name);
226
+ }
227
+ }
228
+
229
+ function mmb_get_sitemeta_transient($option_name){
230
+ global $wpdb;
231
+ $option_name = '_site_transient_'. $option_name;
232
+
233
+ $result = $wpdb->get_var( $wpdb->prepare("SELECT `meta_value` FROM `{$wpdb->sitemeta}` WHERE meta_key = '{$option_name}' AND `site_id` = '{$this->mmb_multisite}' "));
234
+ $result = maybe_unserialize($result);
235
+ return $result;
236
+ }
237
+
238
+ function mmb_set_sitemeta_transient($option_name, $option_value){
239
+ global $wpdb;
240
+ $option_name = '_site_transient_'. $option_name;
241
+
242
+ if($this->mmb_get_sitemeta_transient($option_name)){
243
+ $result = $wpdb->update( $wpdb->sitemeta,
244
+ array(
245
+ 'meta_value' => maybe_serialize($option_value)
246
+ ),
247
+ array(
248
+ 'meta_key' => $option_name,
249
+ 'site_id' => $this->mmb_multisite
250
+ )
251
+ );
252
+ }else {
253
+ $result = $wpdb->insert( $wpdb->sitemeta,
254
+ array(
255
+ 'meta_key' => $option_name,
256
+ 'meta_value' => maybe_serialize($option_value),
257
+ 'site_id' => $this->mmb_multisite
258
+ )
259
+ );
260
+ }
261
+ return $result;
262
+ }
263
+
264
+ function delete_temp_dir($directory)
265
+ {
266
+ if (substr($directory, -1) == "/") {
267
+ $directory = substr($directory, 0, -1);
268
+ }
269
+ if (!file_exists($directory) || !is_dir($directory)) {
270
+ return false;
271
+ } elseif (!is_readable($directory)) {
272
+ return false;
273
+ } else {
274
+ $directoryHandle = opendir($directory);
275
+
276
+ while ($contents = readdir($directoryHandle)) {
277
+ if ($contents != '.' && $contents != '..') {
278
+ $path = $directory . "/" . $contents;
279
+
280
+ if (is_dir($path)) {
281
+ $this->delete_temp_dir($path);
282
+ } else {
283
+ unlink($path);
284
+ }
285
+ }
286
+ }
287
+ closedir($directoryHandle);
288
+ rmdir($directory);
289
+ return true;
290
+ }
291
+ }
292
+
293
+ function set_worker_message_id($message_id = false)
294
+ {
295
+ if ($message_id) {
296
+ add_option('_action_message_id', $message_id) or update_option('_action_message_id', $message_id);
297
+ return $message_id;
298
+ }
299
+ return false;
300
+ }
301
+
302
+ function get_worker_message_id()
303
+ {
304
+ return (int) get_option('_action_message_id');
305
+ }
306
+
307
+ function set_master_public_key($public_key = false)
308
+ {
309
+ if ($public_key && !get_option('_worker_public_key')) {
310
+ add_option('_worker_public_key', base64_encode($public_key));
311
+ return true;
312
+ }
313
+ return false;
314
+ }
315
+
316
+ function get_master_public_key()
317
+ {
318
+ if (!get_option('_worker_public_key'))
319
+ return false;
320
+ return base64_decode(get_option('_worker_public_key'));
321
+ }
322
+
323
+
324
+ function get_random_signature()
325
+ {
326
+ if (!get_option('_worker_nossl_key'))
327
+ return false;
328
+ return base64_decode(get_option('_worker_nossl_key'));
329
+ }
330
+
331
+ function set_random_signature($random_key = false)
332
+ {
333
+ if ($random_key && !get_option('_worker_nossl_key')) {
334
+ add_option('_worker_nossl_key', base64_encode($random_key));
335
+ return true;
336
+ }
337
+ return false;
338
+ }
339
+
340
+
341
+ function authenticate_message($data = false, $signature = false, $message_id = false)
342
+ {
343
+ if (!$data && !$signature) {
344
+ return array(
345
+ 'error' => 'Authentication failed.'
346
+ );
347
+ }
348
+
349
+ $current_message = $this->get_worker_message_id();
350
+
351
+ if ((int) $current_message >= (int) $message_id)
352
+ return array(
353
+ 'error' => 'Invalid message recieved. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
354
+ );
355
+
356
+ $pl_key = $this->get_master_public_key();
357
+ if (!$pl_key) {
358
+ return array(
359
+ 'error' => 'Authentication failed. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
360
+ );
361
+ }
362
+
363
+ if (function_exists('openssl_verify') && !$this->get_random_signature()) {
364
+ $verify = openssl_verify($data, $signature, $pl_key);
365
+ if ($verify == 1) {
366
+ $message_id = $this->set_worker_message_id($message_id);
367
+ return true;
368
+ } else if ($verify == 0) {
369
+ return array(
370
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
371
+ );
372
+ } else {
373
+ return array(
374
+ 'error' => 'Command not successful! Please try again.'
375
+ );
376
+ }
377
+ } else if ($this->get_random_signature()) {
378
+ if (md5($data . $this->get_random_signature()) == $signature) {
379
+ $message_id = $this->set_worker_message_id($message_id);
380
+ return true;
381
+ }
382
+ return array(
383
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
384
+ );
385
+ }
386
+ // no rand key - deleted in get_stat maybe
387
+ else
388
+ return array(
389
+ 'error' => 'Invalid message signature. Deactivate and activate the ManageWP Worker plugin on this site, then remove the website from your ManageWP account and add it again.'
390
+ );
391
+ }
392
+
393
+ function get_secure_hash(){
394
+
395
+ $pl_key = $this->get_master_public_key();
396
+ if ( empty($pl_key) )
397
+ $pl_key = $this->get_random_signature();
398
+
399
+ if( !empty($pl_key) )
400
+ return md5(base64_encode($pl_key));
401
+
402
+ return false;
403
+ }
404
+
405
+ function _secure_data($data = false){
406
+ if($data == false)
407
+ return false;
408
+
409
+ $pl_key = $this->get_master_public_key();
410
+ if (!$pl_key)
411
+ return false;
412
+
413
+ $secure = '';
414
+ if( function_exists('openssl_public_decrypt') && !$this->get_random_signature() ){
415
+ if(is_array($data) && !empty($data)){
416
+ foreach($data as $input){
417
+ openssl_public_decrypt($input, $decrypted, $pl_key);
418
+ $secure .= $decrypted;
419
+ }
420
+ } else if ( is_string( $data ) ) {
421
+ openssl_public_decrypt($data, $decrypted, $pl_key);
422
+ $secure = $decrypted;
423
+ } else {
424
+ $secure = $data;
425
+ }
426
+ return $secure;
427
+ }
428
+ return false;
429
+
430
+ }
431
+
432
+ function encrypt_data( $data = false, $single = false ){
433
+ if( empty($data) )
434
+ return $data;
435
+
436
+ $pl_key = $this->get_master_public_key();
437
+ if ( !$pl_key )
438
+ return false;
439
+
440
+ $data = serialize( $data );
441
+ $crypted = '';
442
+ if( function_exists('openssl_public_encrypt') && !$this->get_random_signature() ){
443
+ $length = strlen( $data );
444
+ if( $length > 100 ){
445
+ for($i = 0; $i <= $length + 100; $i = $i+100){
446
+ $input = substr($data, $i, 100);
447
+ openssl_public_encrypt($input, $crypt, $pl_key);
448
+ $crypted .= base64_encode($crypt).'::';
449
+ }
450
+ } else
451
+ openssl_public_encrypt($input, $crypted, $pl_key);
452
+ } else {
453
+ $crypted = base64_encode($data);
454
+ }
455
+
456
+ return $crypted;
457
+
458
+ }
459
+
460
+ function check_if_user_exists($username = false)
461
+ {
462
+ global $wpdb;
463
+ if ($username) {
464
+ if( !function_exists('username_exists') )
465
+ include_once(ABSPATH . WPINC . '/registration.php');
466
+
467
+ include_once(ABSPATH . 'wp-includes/pluggable.php');
468
+
469
+ if (username_exists($username) == null) {
470
+ return false;
471
+ }
472
+
473
+ $user = (array) $this->mmb_get_user_info( $username );
474
+ if ((isset($user[$wpdb->prefix . 'user_level']) && $user[$wpdb->prefix . 'user_level'] == 10) || isset($user[$wpdb->prefix . 'capabilities']['administrator']) ||
475
+ (isset($user['caps']['administrator']) && $user['caps']['administrator'] == 1)){
476
+ return true;
477
+ }
478
+ return false;
479
+ }
480
+ return false;
481
+ }
482
+
483
+ function refresh_updates()
484
+ {
485
+ if (rand(1, 3) == '2') {
486
+ require_once(ABSPATH . WPINC . '/update.php');
487
+ wp_update_plugins();
488
+ wp_update_themes();
489
+ wp_version_check();
490
+ }
491
+ }
492
+
493
+ function remove_http($url = '')
494
+ {
495
+ if ($url == 'http://' OR $url == 'https://') {
496
+ return $url;
497
+ }
498
+ return preg_replace('/^(http|https)\:\/\/(www.)?/i', '', $url);
499
+
500
+ }
501
+
502
+ function mmb_get_error($error_object)
503
+ {
504
+ if (!is_wp_error($error_object)) {
505
+ return $error_object != '' ? $error_object : '';
506
+ } else {
507
+ $errors = array();
508
+ if(!empty($error_object->error_data)) {
509
+ foreach ($error_object->error_data as $error_key => $error_string) {
510
+ $errors[] = str_replace('_', ' ', ucfirst($error_key)) . ': ' . $error_string;
511
+ }
512
+ } elseif (!empty($error_object->errors)){
513
+ foreach ($error_object->errors as $error_key => $err) {
514
+ $errors[] = 'Error: '.str_replace('_', ' ', strtolower($error_key));
515
+ }
516
+ }
517
+ return implode('<br />', $errors);
518
+ }
519
+ }
520
+
521
+ function is_server_writable(){
522
+ if((!defined('FTP_HOST') || !defined('FTP_USER') || !defined('FTP_PASS')) && (get_filesystem_method(array(), false) != 'direct'))
523
+ return false;
524
+ else
525
+ return true;
526
+ }
527
+
528
+ function mmb_download_url($url, $file_name)
529
+ {
530
+ if (function_exists('fopen') && function_exists('ini_get') && ini_get('allow_url_fopen') == true && ($destination = @fopen($file_name, 'wb')) && ($source = @fopen($url, "r")) ) {
531
+
532
+ while ($a = @fread($source, 1024* 1024)) {
533
+ @fwrite($destination, $a);
534
+ }
535
+
536
+ fclose($source);
537
+ fclose($destination);
538
+ } else
539
+ if (!fsockopen_download($url, $file_name))
540
+ die('Error downloading file ' . $url);
541
+ return $file_name;
542
+ }
543
+
544
+ }
545
  ?>
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: ManageWP - Worker
4
  Plugin URI: http://managewp.com/
5
  Description: Manage all your blogs from one dashboard. Visit <a href="http://managewp.com">ManageWP.com</a> to sign up.
6
  Author: Prelovac Media
7
- Version: 3.9.19
8
  Author URI: http://www.prelovac.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.19');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
@@ -118,6 +118,9 @@ if( !function_exists ( 'mmb_parse_request' )) {
118
  ob_start();
119
 
120
  global $current_user, $mmb_core, $new_actions, $wp_db_version, $wpmu_version, $_wp_using_ext_object_cache, $_mmb_options;
 
 
 
121
  $data = base64_decode($HTTP_RAW_POST_DATA);
122
  if ($data){
123
  $data = mmb_parse_data( unserialize( $data ) );
@@ -752,6 +755,65 @@ if( !function_exists ('mmb_delete_links')) {
752
  }
753
  }
754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  if( !function_exists ( 'mmb_add_user' )) {
756
  function mmb_add_user($params)
757
  {
@@ -924,6 +986,20 @@ if( !function_exists ( 'mmb_set_alerts' )) {
924
  }
925
 
926
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
927
 
928
  if( !function_exists('mmb_more_reccurences') ){
929
  //Backup Tasks
@@ -934,7 +1010,8 @@ if( !function_exists('mmb_more_reccurences') ){
934
  $schedules['fiveminutes'] = array('interval' => 300, 'display' => 'Once every five minutes');
935
  $schedules['tenminutes'] = array('interval' => 600, 'display' => 'Once every ten minutes');
936
  $schedules['sixhours'] = array('interval' => 21600, 'display' => 'Every six hours');
937
- $schedules['fourhours'] = array('interval' => 14400, 'display' => 'Every six hours');
 
938
 
939
  return $schedules;
940
  }
@@ -959,7 +1036,7 @@ if( !function_exists('mwp_check_backup_tasks') ){
959
 
960
 
961
  if (!wp_next_scheduled('mwp_datasend')) {
962
- wp_schedule_event( time(), 'fourhours', 'mwp_datasend' );
963
  }
964
  add_action('mwp_datasend', 'mwp_datasend');
965
 
@@ -1063,6 +1140,10 @@ if( !function_exists('mmb_plugin_actions') ){
1063
  }
1064
  }
1065
  }
 
 
 
 
1066
  }
1067
  }
1068
 
@@ -1082,10 +1163,22 @@ if (function_exists('add_action'))
1082
 
1083
  if (function_exists('add_filter'))
1084
  add_filter('install_plugin_complete_actions','mmb_iframe_plugins_fix');
1085
-
 
 
 
 
 
 
 
 
 
 
 
1086
  if( isset($_COOKIE[MMB_XFRAME_COOKIE]) ){
1087
  remove_action( 'admin_init', 'send_frame_options_header');
1088
  remove_action( 'login_init', 'send_frame_options_header');
1089
  }
1090
 
 
1091
  ?>
4
  Plugin URI: http://managewp.com/
5
  Description: Manage all your blogs from one dashboard. Visit <a href="http://managewp.com">ManageWP.com</a> to sign up.
6
  Author: Prelovac Media
7
+ Version: 3.9.20
8
  Author URI: http://www.prelovac.com
9
  */
10
 
22
  exit;
23
  endif;
24
  if(!defined('MMB_WORKER_VERSION'))
25
+ define('MMB_WORKER_VERSION', '3.9.20');
26
 
27
  if ( !defined('MMB_XFRAME_COOKIE')){
28
  $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
118
  ob_start();
119
 
120
  global $current_user, $mmb_core, $new_actions, $wp_db_version, $wpmu_version, $_wp_using_ext_object_cache, $_mmb_options;
121
+ if(substr($HTTP_RAW_POST_DATA, 0, 7) == "action="){
122
+ $HTTP_RAW_POST_DATA = str_replace("action=", "", $HTTP_RAW_POST_DATA);
123
+ }
124
  $data = base64_decode($HTTP_RAW_POST_DATA);
125
  if ($data){
126
  $data = mmb_parse_data( unserialize( $data ) );
755
  }
756
  }
757
 
758
+ if( !function_exists ('mmb_get_comments')) {
759
+ function mmb_get_comments($params)
760
+ {
761
+ global $mmb_core;
762
+ $mmb_core->get_comment_instance();
763
+ $return = $mmb_core->comment_instance->get_comments($params);
764
+ if (is_array($return) && array_key_exists('error', $return))
765
+ mmb_response($return['error'], false);
766
+ else {
767
+ mmb_response($return, true);
768
+ }
769
+ }
770
+ }
771
+
772
+ if( !function_exists ('mmb_action_comment')) {
773
+ function mmb_action_comment($params)
774
+ {
775
+ global $mmb_core;
776
+ $mmb_core->get_comment_instance();
777
+
778
+ $return = $mmb_core->comment_instance->action_comment($params);
779
+ if (is_array($return) && array_key_exists('error', $return))
780
+ mmb_response($return['error'], false);
781
+ else {
782
+ mmb_response($return, true);
783
+ }
784
+ }
785
+ }
786
+
787
+ if( !function_exists ('mmb_bulk_action_comments')) {
788
+ function mmb_bulk_action_comments($params)
789
+ {
790
+ global $mmb_core;
791
+ $mmb_core->get_comment_instance();
792
+
793
+ $return = $mmb_core->comment_instance->bulk_action_comments($params);
794
+ if (is_array($return) && array_key_exists('error', $return))
795
+ mmb_response($return['error'], false);
796
+ else {
797
+ mmb_response($return, true);
798
+ }
799
+ }
800
+ }
801
+
802
+ if( !function_exists ('mmb_reply_comment')) {
803
+ function mmb_reply_comment($params)
804
+ {
805
+ global $mmb_core;
806
+ $mmb_core->get_comment_instance();
807
+
808
+ $return = $mmb_core->comment_instance->reply_comment($params);
809
+ if (is_array($return) && array_key_exists('error', $return))
810
+ mmb_response($return['error'], false);
811
+ else {
812
+ mmb_response($return, true);
813
+ }
814
+ }
815
+ }
816
+
817
  if( !function_exists ( 'mmb_add_user' )) {
818
  function mmb_add_user($params)
819
  {
986
  }
987
 
988
  }
989
+ if( !function_exists ('mmb_get_dbname')) {
990
+ function mmb_get_dbname($params)
991
+ {
992
+ global $mmb_core;
993
+ $mmb_core->get_stats_instance();
994
+
995
+ $return = $mmb_core->stats_instance->get_active_db();
996
+ if (is_array($return) && array_key_exists('error', $return))
997
+ mmb_response($return['error'], false);
998
+ else {
999
+ mmb_response($return, true);
1000
+ }
1001
+ }
1002
+ }
1003
 
1004
  if( !function_exists('mmb_more_reccurences') ){
1005
  //Backup Tasks
1010
  $schedules['fiveminutes'] = array('interval' => 300, 'display' => 'Once every five minutes');
1011
  $schedules['tenminutes'] = array('interval' => 600, 'display' => 'Once every ten minutes');
1012
  $schedules['sixhours'] = array('interval' => 21600, 'display' => 'Every six hours');
1013
+ $schedules['fourhours'] = array('interval' => 14400, 'display' => 'Every four hours');
1014
+ $schedules['threehours'] = array('interval' => 10800, 'display' => 'Every three hours');
1015
 
1016
  return $schedules;
1017
  }
1036
 
1037
 
1038
  if (!wp_next_scheduled('mwp_datasend')) {
1039
+ wp_schedule_event( time(), 'threehours', 'mwp_datasend' );
1040
  }
1041
  add_action('mwp_datasend', 'mwp_datasend');
1042
 
1140
  }
1141
  }
1142
  }
1143
+
1144
+ if (file_exists(dirname(__FILE__) . '/log')) {
1145
+ unlink(dirname(__FILE__) . '/log');
1146
+ }
1147
  }
1148
  }
1149
 
1163
 
1164
  if (function_exists('add_filter'))
1165
  add_filter('install_plugin_complete_actions','mmb_iframe_plugins_fix');
1166
+
1167
+ if(!function_exists('mwb_edit_redirect_override')){
1168
+ function mwb_edit_redirect_override($location = false, $comment_id = false){
1169
+ if(isset($_COOKIE[MMB_XFRAME_COOKIE])){
1170
+ $location = get_site_url().'/wp-admin/edit-comments.php';
1171
+ }
1172
+ return $location;
1173
+ }
1174
+ }
1175
+ if (function_exists('add_filter'))
1176
+ add_filter('comment_edit_redirect', 'mwb_edit_redirect_override');
1177
+
1178
  if( isset($_COOKIE[MMB_XFRAME_COOKIE]) ){
1179
  remove_action( 'admin_init', 'send_frame_options_header');
1180
  remove_action( 'login_init', 'send_frame_options_header');
1181
  }
1182
 
1183
+
1184
  ?>
installer.class.php CHANGED
@@ -1,874 +1,874 @@
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
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "installer.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Installer extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- @set_time_limit(600);
20
- parent::__construct();
21
- @include_once(ABSPATH . 'wp-admin/includes/file.php');
22
- @include_once(ABSPATH . 'wp-admin/includes/plugin.php');
23
- @include_once(ABSPATH . 'wp-admin/includes/theme.php');
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);
42
- $wp_filesystem->put_contents($file, $maintenance_message, FS_CHMOD_FILE);
43
- } else {
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(
76
- 'package' => $package_url,
77
- 'destination' => $destination,
78
- 'clear_destination' => $clear_destination, //Do not overwrite files.
79
- 'clear_working' => true,
80
- 'hook_extra' => array()
81
- ));
82
- }
83
-
84
- if ($activate) {
85
- if ($type == 'plugins') {
86
- include_once(ABSPATH . 'wp-admin/includes/plugin.php');
87
- $all_plugins = get_plugins();
88
- foreach ($all_plugins as $plugin_slug => $plugin) {
89
- $plugin_dir = preg_split('/\//', $plugin_slug);
90
- foreach ($install_info as $key => $install) {
91
- if (!$install || is_wp_error($install))
92
- continue;
93
- if ($install['destination_name'] == $plugin_dir[0]) {
94
- $install_info[$key]['activated'] = activate_plugin($plugin_slug, '', false);
95
- }
96
- }
97
- }
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
-
105
- $all_themes = get_themes();
106
- foreach ($all_themes as $theme_name => $theme_data) {
107
- foreach ($install_info as $key => $install) {
108
- if (!$install || is_wp_error($install))
109
- continue;
110
-
111
- if ($theme_data['Template'] == $install['destination_name']) {
112
- $install_info[$key]['activated'] = switch_theme($theme_data['Template'], $theme_data['Stylesheet']);
113
- }
114
- }
115
- }
116
- }
117
- }
118
- ob_clean();
119
- $this->mmb_maintenance_mode(false);
120
- return $install_info;
121
- }
122
-
123
- function do_upgrade($params = null)
124
- {
125
- if ($params == null || empty($params))
126
- return array(
127
- 'failed' => 'No upgrades passed.'
128
- );
129
-
130
- if (!$this->is_server_writable()) {
131
- return array(
132
- '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>'
133
- );
134
- }
135
-
136
-
137
- $params = isset($params['upgrades_all']) ? $params['upgrades_all'] : $params;
138
-
139
- $core_upgrade = isset($params['wp_upgrade']) ? $params['wp_upgrade'] : array();
140
- $upgrade_plugins = isset($params['upgrade_plugins']) ? $params['upgrade_plugins'] : array();
141
- $upgrade_themes = isset($params['upgrade_themes']) ? $params['upgrade_themes'] : array();
142
-
143
- $upgrades = array();
144
- $premium_upgrades = array();
145
- if (!empty($core_upgrade)) {
146
- $upgrades['core'] = $this->upgrade_core($core_upgrade);
147
- }
148
-
149
- if (!empty($upgrade_plugins)) {
150
- $plugin_files = array();
151
- foreach ($upgrade_plugins as $plugin) {
152
- if (isset($plugin->file))
153
- $plugin_files[$plugin->file] = $plugin->old_version;
154
- else
155
- $premium_upgrades[md5($plugin->name)] = $plugin;
156
- }
157
- if (!empty($plugin_files))
158
- $upgrades['plugins'] = $this->upgrade_plugins($plugin_files);
159
-
160
- }
161
-
162
- if (!empty($upgrade_themes)) {
163
- $theme_temps = array();
164
- foreach ($upgrade_themes as $theme) {
165
- if (isset($theme['theme_tmp']))
166
- $theme_temps[] = $theme['theme_tmp'];
167
- else
168
- $premium_upgrades[md5($theme['name'])] = $theme;
169
- }
170
-
171
- if (!empty($theme_temps))
172
- $upgrades['themes'] = $this->upgrade_themes($theme_temps);
173
-
174
- }
175
-
176
- if (!empty($premium_upgrades)) {
177
- $premium_upgrades = $this->upgrade_premium($premium_upgrades);
178
- if (!empty($premium_upgrades)) {
179
- if (!empty($upgrades)) {
180
- foreach ($upgrades as $key => $val) {
181
- if (isset($premium_upgrades[$key])) {
182
- $upgrades[$key] = array_merge_recursive($upgrades[$key], $premium_upgrades[$key]);
183
- }
184
- }
185
- } else {
186
- $upgrades = $premium_upgrades;
187
- }
188
- }
189
- }
190
- ob_clean();
191
- $this->mmb_maintenance_mode(false);
192
- return $upgrades;
193
- }
194
-
195
- /**
196
- * Upgrades WordPress locally
197
- *
198
- */
199
- function upgrade_core($current)
200
- {
201
- ob_start();
202
- if (!function_exists('wp_version_check'))
203
- include_once(ABSPATH . '/wp-admin/includes/update.php');
204
-
205
- @wp_version_check();
206
-
207
- $current_update = false;
208
- ob_end_flush();
209
- ob_end_clean();
210
- $core = $this->mmb_get_transient('update_core');
211
-
212
- if (isset($core->updates) && !empty($core->updates)) {
213
- $updates = $core->updates[0];
214
- $updated = $core->updates[0];
215
- if (!isset($updated->response) || $updated->response == 'latest')
216
- return array(
217
- 'upgraded' => ' updated'
218
- );
219
-
220
- if ($updated->response == "development" && $current->response == "upgrade") {
221
- return array(
222
- 'upgraded' => '<font color="#900">Unexpected error. Please upgrade manually.</font>'
223
- );
224
- } else if ($updated->response == $current->response || ($updated->response == "upgrade" && $current->response == "development")) {
225
- if ($updated->locale != $current->locale) {
226
- foreach ($updates as $update) {
227
- if ($update->locale == $current->locale) {
228
- $current_update = $update;
229
- break;
230
- }
231
- }
232
- if ($current_update == false)
233
- return array(
234
- 'error' => ' Localization mismatch. Try again.'
235
- );
236
- } else {
237
- $current_update = $updated;
238
- }
239
- } else
240
- return array(
241
- 'error' => ' Transient mismatch. Try again.'
242
- );
243
- } else
244
- return array(
245
- 'error' => ' Refresh transient failed. Try again.'
246
- );
247
- if ($current_update != false) {
248
- global $mmb_wp_version, $wp_filesystem, $wp_version;
249
-
250
- if (version_compare($wp_version, '3.1.9', '>')) {
251
- if (!class_exists('Core_Upgrader'))
252
- include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
253
-
254
- $core = new Core_Upgrader();
255
- $result = $core->upgrade($current_update);
256
- $this->mmb_maintenance_mode(false);
257
- if (is_wp_error($result)) {
258
- return array(
259
- 'error' => $this->mmb_get_error($result)
260
- );
261
- } else
262
- return array(
263
- 'upgraded' => ' updated'
264
- );
265
-
266
- } else {
267
- if (!class_exists('WP_Upgrader')) {
268
- include_once(ABSPATH . 'wp-admin/includes/update.php');
269
- if (function_exists('wp_update_core')) {
270
- $result = wp_update_core($current_update);
271
- if (is_wp_error($result)) {
272
- return array(
273
- 'error' => $this->mmb_get_error($result)
274
- );
275
- } else
276
- return array(
277
- 'upgraded' => ' updated'
278
- );
279
- }
280
- }
281
-
282
- if (class_exists('WP_Upgrader')) {
283
- $upgrader_skin = new WP_Upgrader_Skin();
284
- $upgrader_skin->done_header = true;
285
-
286
- $upgrader = new WP_Upgrader($upgrader_skin);
287
-
288
- // Is an update available?
289
- if (!isset($current_update->response) || $current_update->response == 'latest')
290
- return array(
291
- 'upgraded' => ' updated'
292
- );
293
-
294
- $res = $upgrader->fs_connect(array(
295
- ABSPATH,
296
- WP_CONTENT_DIR
297
- ));
298
- if (is_wp_error($res))
299
- return array(
300
- 'error' => $this->mmb_get_error($res)
301
- );
302
-
303
- $wp_dir = trailingslashit($wp_filesystem->abspath());
304
-
305
- $core_package = false;
306
- if (isset($current_update->package) && !empty($current_update->package))
307
- $core_package = $current_update->package;
308
- elseif (isset($current_update->packages->full) && !empty($current_update->packages->full))
309
- $core_package = $current_update->packages->full;
310
-
311
- $download = $upgrader->download_package($core_package);
312
- if (is_wp_error($download))
313
- return array(
314
- 'error' => $this->mmb_get_error($download)
315
- );
316
-
317
- $working_dir = $upgrader->unpack_package($download);
318
- if (is_wp_error($working_dir))
319
- return array(
320
- 'error' => $this->mmb_get_error($working_dir)
321
- );
322
-
323
- if (!$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true)) {
324
- $wp_filesystem->delete($working_dir, true);
325
- return array(
326
- 'error' => 'Unable to move update files.'
327
- );
328
- }
329
-
330
- $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
331
-
332
- require(ABSPATH . 'wp-admin/includes/update-core.php');
333
-
334
-
335
- $update_core = update_core($working_dir, $wp_dir);
336
- ob_end_clean();
337
-
338
- $this->mmb_maintenance_mode(false);
339
- if (is_wp_error($update_core))
340
- return array(
341
- 'error' => $this->mmb_get_error($update_core)
342
- );
343
- ob_end_flush();
344
- return array(
345
- 'upgraded' => 'updated'
346
- );
347
- } else {
348
- return array(
349
- 'error' => 'failed'
350
- );
351
- }
352
- }
353
- } else {
354
- return array(
355
- 'error' => 'failed'
356
- );
357
- }
358
- }
359
-
360
- function upgrade_plugins($plugins = false)
361
- {
362
- if (!$plugins || empty($plugins))
363
- return array(
364
- 'error' => 'No plugin files for upgrade.'
365
- );
366
-
367
- $current = $this->mmb_get_transient('update_plugins');
368
- $versions = array();
369
- if(!empty($current)){
370
- foreach($plugins as $plugin => $data){
371
- if(isset($current->checked[$plugin])){
372
- $versions[$current->checked[$plugin]] = $plugin;
373
- }
374
- }
375
- }
376
- $return = array();
377
- if (class_exists('Plugin_Upgrader') && class_exists('Bulk_Plugin_Upgrader_Skin')) {
378
- $upgrader = new Plugin_Upgrader(new Bulk_Plugin_Upgrader_Skin(compact('nonce', 'url')));
379
- $result = $upgrader->bulk_upgrade(array_keys($plugins));
380
- if (!function_exists('wp_update_plugins'))
381
- include_once(ABSPATH . 'wp-includes/update.php');
382
-
383
- @wp_update_plugins();
384
- $current = $this->mmb_get_transient('update_plugins');
385
- if (!empty($result)) {
386
- foreach ($result as $plugin_slug => $plugin_info) {
387
- if (!$plugin_info || is_wp_error($plugin_info)) {
388
- $return[$plugin_slug] = $this->mmb_get_error($plugin_info);
389
- } else {
390
- if(!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)){
391
- $return[$plugin_slug] = 1;
392
- } else {
393
- update_option('mmb_forcerefresh', true);
394
- $return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
395
- }
396
- }
397
- }
398
- ob_end_clean();
399
- return array(
400
- 'upgraded' => $return
401
- );
402
- } else
403
- return array(
404
- 'error' => 'Upgrade failed.'
405
- );
406
- } else {
407
- ob_end_clean();
408
- return array(
409
- 'error' => 'WordPress update required first.'
410
- );
411
- }
412
- }
413
-
414
- function upgrade_themes($themes = false)
415
- {
416
- if (!$themes || empty($themes))
417
- return array(
418
- 'error' => 'No theme files for upgrade.'
419
- );
420
-
421
- $current = $this->mmb_get_transient('update_themes');
422
- $versions = array();
423
- if(!empty($current)){
424
- foreach($themes as $theme){
425
- if(isset($current->checked[$theme])){
426
- $versions[$current->checked[$theme]] = $theme;
427
- }
428
- }
429
- }
430
- if (class_exists('Theme_Upgrader') && class_exists('Bulk_Theme_Upgrader_Skin')) {
431
- $upgrader = new Theme_Upgrader(new Bulk_Theme_Upgrader_Skin(compact('title', 'nonce', 'url', 'theme')));
432
- $result = $upgrader->bulk_upgrade($themes);
433
-
434
- if (!function_exists('wp_update_themes'))
435
- include_once(ABSPATH . 'wp-includes/update.php');
436
-
437
- @wp_update_themes();
438
- $current = $this->mmb_get_transient('update_themes');
439
- $return = array();
440
- if (!empty($result)) {
441
- foreach ($result as $theme_tmp => $theme_info) {
442
- if (is_wp_error($theme_info) || empty($theme_info)) {
443
- $return[$theme_tmp] = $this->mmb_get_error($theme_info);
444
- } else {
445
- if(!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)){
446
- $return[$theme_tmp] = 1;
447
- } else {
448
- update_option('mmb_forcerefresh', true);
449
- $return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
450
- }
451
- }
452
- }
453
- return array(
454
- 'upgraded' => $return
455
- );
456
- } else
457
- return array(
458
- 'error' => 'Upgrade failed.'
459
- );
460
- } else {
461
- ob_end_clean();
462
- return array(
463
- 'error' => 'WordPress update required first'
464
- );
465
- }
466
- }
467
-
468
- function upgrade_premium($premium = false)
469
- {
470
- global $mmb_plugin_url;
471
-
472
- if (!class_exists('WP_Upgrader'))
473
- include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
474
-
475
- if (!$premium || empty($premium))
476
- return array(
477
- 'error' => 'No premium files for upgrade.'
478
- );
479
-
480
- $upgrader = false;
481
- $pr_update = array();
482
- $themes = array();
483
- $plugins = array();
484
- $result = array();
485
- $premium_update = array();
486
- $premium_update = apply_filters('mwp_premium_perform_update', $premium_update);
487
- if (!empty($premium_update)) {
488
-
489
- foreach ($premium as $pr) {
490
- foreach ($premium_update as $key => $update) {
491
- $update = array_change_key_case($update, CASE_LOWER);
492
- if ($update['name'] == $pr['name']) {
493
-
494
- // prepare bulk updates for premiums that use WordPress upgrader
495
- if(isset($update['type'])){
496
- if($update['type'] == 'plugin'){
497
- if(isset($update['slug']) && !empty($update['slug']))
498
- $plugins[$update['slug']] = $update;
499
- }
500
-
501
- if($update['type'] == 'theme'){
502
- if(isset($update['template']) && !empty($update['template']))
503
- $themes[$update['template']] = $update;
504
- }
505
- }
506
- } else {
507
- unset($premium_update[$key]);
508
- }
509
- }
510
- }
511
-
512
- // try default wordpress upgrader
513
- if(!empty($plugins)){
514
- $updateplugins = $this->upgrade_plugins(array_keys($plugins));
515
- if(!empty($updateplugins) && isset($updateplugins['upgraded'])){
516
- foreach ($premium_update as $key => $update) {
517
- $update = array_change_key_case($update, CASE_LOWER);
518
- foreach($updateplugins['upgraded'] as $slug => $upgrade){
519
- if( isset($update['slug']) && $update['slug'] == $slug){
520
- if( $upgrade == 1 )
521
- unset($premium_update[$key]);
522
-
523
- $pr_update['plugins']['upgraded'][md5($update['name'])] = $upgrade;
524
- }
525
- }
526
- }
527
- }
528
- }
529
-
530
- if(!empty($themes)){
531
- $updatethemes = $this->upgrade_themes(array_keys($themes));
532
- if(!empty($updatethemes) && isset($updatethemes['upgraded'])){
533
- foreach ($premium_update as $key => $update) {
534
- $update = array_change_key_case($update, CASE_LOWER);
535
- foreach($updatethemes['upgraded'] as $template => $upgrade){
536
- if( isset($update['template']) && $update['template'] == $template) {
537
- if( $upgrade == 1 )
538
- unset($premium_update[$key]);
539
-
540
- $pr_update['themes']['upgraded'][md5($update['name'])] = $upgrade;
541
- }
542
- }
543
- }
544
- }
545
- }
546
-
547
- //try direct install with overwrite
548
- if(!empty($premium_update)){
549
- foreach ($premium_update as $update) {
550
- $update = array_change_key_case($update, CASE_LOWER);
551
- $update_result = false;
552
- if (isset($update['url'])) {
553
- if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
554
- $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
555
-
556
- $upgrader_skin = new WP_Upgrader_Skin();
557
- $upgrader_skin->done_header = true;
558
- $upgrader = new WP_Upgrader();
559
- @$update_result = $upgrader->run(array(
560
- 'package' => $update['url'],
561
- 'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
562
- 'clear_destination' => true,
563
- 'clear_working' => true,
564
- 'is_multi' => true,
565
- 'hook_extra' => array()
566
- ));
567
- $update_result = !$update_result || is_wp_error($update_result) ? $this->mmb_get_error($update_result) : 1;
568
-
569
- } else if (isset($update['callback'])) {
570
- if (is_array($update['callback'])) {
571
- $update_result = call_user_func(array( $update['callback'][0], $update['callback'][1] ));
572
- } else if (is_string($update['callback'])) {
573
- $update_result = call_user_func($update['callback']);
574
- } else {
575
- $update_result = 'Upgrade function "' . $update['callback'] . '" does not exists.';
576
- }
577
-
578
- $update_result = $update_result !== true ? $this->mmb_get_error($update_result) : 1;
579
- } else
580
- $update_result = 'Bad update params.';
581
-
582
- $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
583
- }
584
- }
585
- return $pr_update;
586
- } else {
587
- foreach ($premium as $pr) {
588
- $result[$pr['type'] . 's']['upgraded'][md5($pr['name'])] = 'This premium update is not registered.';
589
- }
590
- return $result;
591
- }
592
- }
593
-
594
- function get_upgradable_plugins( $filter = array() )
595
- {
596
- $current = $this->mmb_get_transient('update_plugins');
597
-
598
- $upgradable_plugins = array();
599
- if (!empty($current->response)) {
600
- if (!function_exists('get_plugin_data'))
601
- include_once ABSPATH . 'wp-admin/includes/plugin.php';
602
- foreach ($current->response as $plugin_path => $plugin_data) {
603
- if ($plugin_path == 'worker/init.php')
604
- continue;
605
-
606
- $data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_path);
607
- if(isset($data['Name']) && in_array($data['Name'], $filter))
608
- continue;
609
-
610
- if (strlen($data['Name']) > 0 && strlen($data['Version']) > 0) {
611
- $current->response[$plugin_path]->name = $data['Name'];
612
- $current->response[$plugin_path]->old_version = $data['Version'];
613
- $current->response[$plugin_path]->file = $plugin_path;
614
- unset($current->response[$plugin_path]->upgrade_notice);
615
- $upgradable_plugins[] = $current->response[$plugin_path];
616
- }
617
- }
618
- return $upgradable_plugins;
619
- } else
620
- return array();
621
- }
622
-
623
- function get_upgradable_themes( $filter = array() )
624
- {
625
- $all_themes = get_themes();
626
- $upgrade_themes = array();
627
-
628
- $current = $this->mmb_get_transient('update_themes');
629
- if (!empty($current->response)) {
630
- foreach ((array) $all_themes as $theme_template => $theme_data) {
631
- if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
632
- continue;
633
-
634
- if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
635
- continue;
636
-
637
- foreach ($current->response as $current_themes => $theme) {
638
- if ($theme_data['Template'] == $current_themes) {
639
- if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
640
- $current->response[$current_themes]['name'] = $theme_data['Name'];
641
- $current->response[$current_themes]['old_version'] = $theme_data['Version'];
642
- $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
643
- $upgrade_themes[] = $current->response[$current_themes];
644
- }
645
- }
646
- }
647
- }
648
- }
649
-
650
- return $upgrade_themes;
651
- }
652
-
653
- function get($args)
654
- {
655
- if (empty($args))
656
- return false;
657
-
658
- //Args: $items('plugins,'themes'), $type (active || inactive), $search(name string)
659
-
660
- $return = array();
661
- if (is_array($args['items']) && in_array('plugins', $args['items'])) {
662
- $return['plugins'] = $this->get_plugins($args);
663
- }
664
- if (is_array($args['items']) && in_array('themes', $args['items'])) {
665
- $return['themes'] = $this->get_themes($args);
666
- }
667
-
668
- return $return;
669
- }
670
-
671
- function get_plugins($args)
672
- {
673
- if (empty($args))
674
- return false;
675
-
676
- extract($args);
677
-
678
- if (!function_exists('get_plugins')) {
679
- include_once(ABSPATH . 'wp-admin/includes/plugin.php');
680
- }
681
- $all_plugins = get_plugins();
682
- $plugins = array(
683
- 'active' => array(),
684
- 'inactive' => array()
685
- );
686
- if (is_array($all_plugins) && !empty($all_plugins)) {
687
- $activated_plugins = get_option('active_plugins');
688
- if (!$activated_plugins)
689
- $activated_plugins = array();
690
-
691
- $br_a = 0;
692
- $br_i = 0;
693
- foreach ($all_plugins as $path => $plugin) {
694
- if ($plugin['Name'] != 'ManageWP - Worker') {
695
- if (in_array($path, $activated_plugins)) {
696
- $plugins['active'][$br_a]['path'] = $path;
697
- $plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
698
- $plugins['active'][$br_a]['version'] = $plugin['Version'];
699
- $br_a++;
700
- }
701
-
702
- if (!in_array($path, $activated_plugins)) {
703
- $plugins['inactive'][$br_i]['path'] = $path;
704
- $plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
705
- $plugins['inactive'][$br_i]['version'] = $plugin['Version'];
706
- $br_i++;
707
- }
708
-
709
- }
710
-
711
- if ($search) {
712
- foreach ($plugins['active'] as $k => $plugin) {
713
- if (!stristr($plugin['name'], $search)) {
714
- unset($plugins['active'][$k]);
715
- }
716
- }
717
-
718
- foreach ($plugins['inactive'] as $k => $plugin) {
719
- if (!stristr($plugin['name'], $search)) {
720
- unset($plugins['inactive'][$k]);
721
- }
722
- }
723
- }
724
- }
725
- }
726
-
727
- return $plugins;
728
- }
729
-
730
- function get_themes($args)
731
- {
732
- if (empty($args))
733
- return false;
734
-
735
- extract($args);
736
-
737
- if (!function_exists('get_themes')) {
738
- include_once(ABSPATH . WPINC . '/theme.php');
739
- }
740
- $all_themes = get_themes();
741
- $themes = array(
742
- 'active' => array(),
743
- 'inactive' => array()
744
- );
745
-
746
- if (is_array($all_themes) && !empty($all_themes)) {
747
- $current_theme = get_current_theme();
748
-
749
- $br_a = 0;
750
- $br_i = 0;
751
- foreach ($all_themes as $theme_name => $theme) {
752
- if ($current_theme == $theme_name) {
753
- $themes['active'][$br_a]['path'] = $theme['Template'];
754
- $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
755
- $themes['active'][$br_a]['version'] = $theme['Version'];
756
- $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
757
- $br_a++;
758
- }
759
-
760
- if ($current_theme != $theme_name) {
761
- $themes['inactive'][$br_i]['path'] = $theme['Template'];
762
- $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
763
- $themes['inactive'][$br_i]['version'] = $theme['Version'];
764
- $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
765
- $br_i++;
766
- }
767
-
768
- }
769
-
770
- if ($search) {
771
- foreach ($themes['active'] as $k => $theme) {
772
- if (!stristr($theme['name'], $search)) {
773
- unset($themes['active'][$k]);
774
- }
775
- }
776
-
777
- foreach ($themes['inactive'] as $k => $theme) {
778
- if (!stristr($theme['name'], $search)) {
779
- unset($themes['inactive'][$k]);
780
- }
781
- }
782
- }
783
- }
784
-
785
- return $themes;
786
- }
787
-
788
- function edit($args)
789
- {
790
- extract($args);
791
- $return = array();
792
- if ($type == 'plugins') {
793
- $return['plugins'] = $this->edit_plugins($args);
794
- } elseif ($type == 'themes') {
795
- $return['themes'] = $this->edit_themes($args);
796
- }
797
- return $return;
798
- }
799
-
800
- function edit_plugins($args)
801
- {
802
- extract($args);
803
- $return = array();
804
- foreach ($items as $item) {
805
- switch ($items_edit_action) {
806
- case 'activate':
807
- $result = activate_plugin($item['path']);
808
- break;
809
- case 'deactivate':
810
- $result = deactivate_plugins(array(
811
- $item['path']
812
- ));
813
- break;
814
- case 'delete':
815
- $result = delete_plugins(array(
816
- $item['path']
817
- ));
818
- break;
819
- default:
820
- break;
821
- }
822
-
823
- if (is_wp_error($result)) {
824
- $result = array(
825
- 'error' => $result->get_error_message()
826
- );
827
- } elseif ($result === false) {
828
- $result = array(
829
- 'error' => "Failed to perform action."
830
- );
831
- } else {
832
- $result = "OK";
833
- }
834
- $return[$item['name']] = $result;
835
- }
836
-
837
- return $return;
838
- }
839
-
840
- function edit_themes($args)
841
- {
842
- extract($args);
843
- $return = array();
844
- foreach ($items as $item) {
845
- switch ($items_edit_action) {
846
- case 'activate':
847
- switch_theme($item['path'], $item['stylesheet']);
848
- break;
849
- case 'delete':
850
- $result = delete_theme($item['path']);
851
- break;
852
- default:
853
- break;
854
- }
855
-
856
- if (is_wp_error($result)) {
857
- $result = array(
858
- 'error' => $result->get_error_message()
859
- );
860
- } elseif ($result === false) {
861
- $result = array(
862
- 'error' => "Failed to perform action."
863
- );
864
- } else {
865
- $result = "OK";
866
- }
867
- $return[$item['name']] = $result;
868
- }
869
-
870
- return $return;
871
-
872
- }
873
- }
874
  ?>
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
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "installer.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Installer extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ @set_time_limit(600);
20
+ parent::__construct();
21
+ @include_once(ABSPATH . 'wp-admin/includes/file.php');
22
+ @include_once(ABSPATH . 'wp-admin/includes/plugin.php');
23
+ @include_once(ABSPATH . 'wp-admin/includes/theme.php');
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);
42
+ $wp_filesystem->put_contents($file, $maintenance_message, FS_CHMOD_FILE);
43
+ } else {
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(
76
+ 'package' => $package_url,
77
+ 'destination' => $destination,
78
+ 'clear_destination' => $clear_destination, //Do not overwrite files.
79
+ 'clear_working' => true,
80
+ 'hook_extra' => array()
81
+ ));
82
+ }
83
+
84
+ if ($activate) {
85
+ if ($type == 'plugins') {
86
+ include_once(ABSPATH . 'wp-admin/includes/plugin.php');
87
+ $all_plugins = get_plugins();
88
+ foreach ($all_plugins as $plugin_slug => $plugin) {
89
+ $plugin_dir = preg_split('/\//', $plugin_slug);
90
+ foreach ($install_info as $key => $install) {
91
+ if (!$install || is_wp_error($install))
92
+ continue;
93
+ if ($install['destination_name'] == $plugin_dir[0]) {
94
+ $install_info[$key]['activated'] = activate_plugin($plugin_slug, '', false);
95
+ }
96
+ }
97
+ }
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
+
105
+ $all_themes = get_themes();
106
+ foreach ($all_themes as $theme_name => $theme_data) {
107
+ foreach ($install_info as $key => $install) {
108
+ if (!$install || is_wp_error($install))
109
+ continue;
110
+
111
+ if ($theme_data['Template'] == $install['destination_name']) {
112
+ $install_info[$key]['activated'] = switch_theme($theme_data['Template'], $theme_data['Stylesheet']);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ ob_clean();
119
+ $this->mmb_maintenance_mode(false);
120
+ return $install_info;
121
+ }
122
+
123
+ function do_upgrade($params = null)
124
+ {
125
+ if ($params == null || empty($params))
126
+ return array(
127
+ 'failed' => 'No upgrades passed.'
128
+ );
129
+
130
+ if (!$this->is_server_writable()) {
131
+ return array(
132
+ '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>'
133
+ );
134
+ }
135
+
136
+
137
+ $params = isset($params['upgrades_all']) ? $params['upgrades_all'] : $params;
138
+
139
+ $core_upgrade = isset($params['wp_upgrade']) ? $params['wp_upgrade'] : array();
140
+ $upgrade_plugins = isset($params['upgrade_plugins']) ? $params['upgrade_plugins'] : array();
141
+ $upgrade_themes = isset($params['upgrade_themes']) ? $params['upgrade_themes'] : array();
142
+
143
+ $upgrades = array();
144
+ $premium_upgrades = array();
145
+ if (!empty($core_upgrade)) {
146
+ $upgrades['core'] = $this->upgrade_core($core_upgrade);
147
+ }
148
+
149
+ if (!empty($upgrade_plugins)) {
150
+ $plugin_files = array();
151
+ foreach ($upgrade_plugins as $plugin) {
152
+ if (isset($plugin->file))
153
+ $plugin_files[$plugin->file] = $plugin->old_version;
154
+ else
155
+ $premium_upgrades[md5($plugin->name)] = $plugin;
156
+ }
157
+ if (!empty($plugin_files))
158
+ $upgrades['plugins'] = $this->upgrade_plugins($plugin_files);
159
+
160
+ }
161
+
162
+ if (!empty($upgrade_themes)) {
163
+ $theme_temps = array();
164
+ foreach ($upgrade_themes as $theme) {
165
+ if (isset($theme['theme_tmp']))
166
+ $theme_temps[] = $theme['theme_tmp'];
167
+ else
168
+ $premium_upgrades[md5($theme['name'])] = $theme;
169
+ }
170
+
171
+ if (!empty($theme_temps))
172
+ $upgrades['themes'] = $this->upgrade_themes($theme_temps);
173
+
174
+ }
175
+
176
+ if (!empty($premium_upgrades)) {
177
+ $premium_upgrades = $this->upgrade_premium($premium_upgrades);
178
+ if (!empty($premium_upgrades)) {
179
+ if (!empty($upgrades)) {
180
+ foreach ($upgrades as $key => $val) {
181
+ if (isset($premium_upgrades[$key])) {
182
+ $upgrades[$key] = array_merge_recursive($upgrades[$key], $premium_upgrades[$key]);
183
+ }
184
+ }
185
+ } else {
186
+ $upgrades = $premium_upgrades;
187
+ }
188
+ }
189
+ }
190
+ ob_clean();
191
+ $this->mmb_maintenance_mode(false);
192
+ return $upgrades;
193
+ }
194
+
195
+ /**
196
+ * Upgrades WordPress locally
197
+ *
198
+ */
199
+ function upgrade_core($current)
200
+ {
201
+ ob_start();
202
+ if (!function_exists('wp_version_check'))
203
+ include_once(ABSPATH . '/wp-admin/includes/update.php');
204
+
205
+ @wp_version_check();
206
+
207
+ $current_update = false;
208
+ ob_end_flush();
209
+ ob_end_clean();
210
+ $core = $this->mmb_get_transient('update_core');
211
+
212
+ if (isset($core->updates) && !empty($core->updates)) {
213
+ $updates = $core->updates[0];
214
+ $updated = $core->updates[0];
215
+ if (!isset($updated->response) || $updated->response == 'latest')
216
+ return array(
217
+ 'upgraded' => ' updated'
218
+ );
219
+
220
+ if ($updated->response == "development" && $current->response == "upgrade") {
221
+ return array(
222
+ 'upgraded' => '<font color="#900">Unexpected error. Please upgrade manually.</font>'
223
+ );
224
+ } else if ($updated->response == $current->response || ($updated->response == "upgrade" && $current->response == "development")) {
225
+ if ($updated->locale != $current->locale) {
226
+ foreach ($updates as $update) {
227
+ if ($update->locale == $current->locale) {
228
+ $current_update = $update;
229
+ break;
230
+ }
231
+ }
232
+ if ($current_update == false)
233
+ return array(
234
+ 'error' => ' Localization mismatch. Try again.'
235
+ );
236
+ } else {
237
+ $current_update = $updated;
238
+ }
239
+ } else
240
+ return array(
241
+ 'error' => ' Transient mismatch. Try again.'
242
+ );
243
+ } else
244
+ return array(
245
+ 'error' => ' Refresh transient failed. Try again.'
246
+ );
247
+ if ($current_update != false) {
248
+ global $mmb_wp_version, $wp_filesystem, $wp_version;
249
+
250
+ if (version_compare($wp_version, '3.1.9', '>')) {
251
+ if (!class_exists('Core_Upgrader'))
252
+ include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
253
+
254
+ $core = new Core_Upgrader();
255
+ $result = $core->upgrade($current_update);
256
+ $this->mmb_maintenance_mode(false);
257
+ if (is_wp_error($result)) {
258
+ return array(
259
+ 'error' => $this->mmb_get_error($result)
260
+ );
261
+ } else
262
+ return array(
263
+ 'upgraded' => ' updated'
264
+ );
265
+
266
+ } else {
267
+ if (!class_exists('WP_Upgrader')) {
268
+ include_once(ABSPATH . 'wp-admin/includes/update.php');
269
+ if (function_exists('wp_update_core')) {
270
+ $result = wp_update_core($current_update);
271
+ if (is_wp_error($result)) {
272
+ return array(
273
+ 'error' => $this->mmb_get_error($result)
274
+ );
275
+ } else
276
+ return array(
277
+ 'upgraded' => ' updated'
278
+ );
279
+ }
280
+ }
281
+
282
+ if (class_exists('WP_Upgrader')) {
283
+ $upgrader_skin = new WP_Upgrader_Skin();
284
+ $upgrader_skin->done_header = true;
285
+
286
+ $upgrader = new WP_Upgrader($upgrader_skin);
287
+
288
+ // Is an update available?
289
+ if (!isset($current_update->response) || $current_update->response == 'latest')
290
+ return array(
291
+ 'upgraded' => ' updated'
292
+ );
293
+
294
+ $res = $upgrader->fs_connect(array(
295
+ ABSPATH,
296
+ WP_CONTENT_DIR
297
+ ));
298
+ if (is_wp_error($res))
299
+ return array(
300
+ 'error' => $this->mmb_get_error($res)
301
+ );
302
+
303
+ $wp_dir = trailingslashit($wp_filesystem->abspath());
304
+
305
+ $core_package = false;
306
+ if (isset($current_update->package) && !empty($current_update->package))
307
+ $core_package = $current_update->package;
308
+ elseif (isset($current_update->packages->full) && !empty($current_update->packages->full))
309
+ $core_package = $current_update->packages->full;
310
+
311
+ $download = $upgrader->download_package($core_package);
312
+ if (is_wp_error($download))
313
+ return array(
314
+ 'error' => $this->mmb_get_error($download)
315
+ );
316
+
317
+ $working_dir = $upgrader->unpack_package($download);
318
+ if (is_wp_error($working_dir))
319
+ return array(
320
+ 'error' => $this->mmb_get_error($working_dir)
321
+ );
322
+
323
+ if (!$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true)) {
324
+ $wp_filesystem->delete($working_dir, true);
325
+ return array(
326
+ 'error' => 'Unable to move update files.'
327
+ );
328
+ }
329
+
330
+ $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
331
+
332
+ require(ABSPATH . 'wp-admin/includes/update-core.php');
333
+
334
+
335
+ $update_core = update_core($working_dir, $wp_dir);
336
+ ob_end_clean();
337
+
338
+ $this->mmb_maintenance_mode(false);
339
+ if (is_wp_error($update_core))
340
+ return array(
341
+ 'error' => $this->mmb_get_error($update_core)
342
+ );
343
+ ob_end_flush();
344
+ return array(
345
+ 'upgraded' => 'updated'
346
+ );
347
+ } else {
348
+ return array(
349
+ 'error' => 'failed'
350
+ );
351
+ }
352
+ }
353
+ } else {
354
+ return array(
355
+ 'error' => 'failed'
356
+ );
357
+ }
358
+ }
359
+
360
+ function upgrade_plugins($plugins = false)
361
+ {
362
+ if (!$plugins || empty($plugins))
363
+ return array(
364
+ 'error' => 'No plugin files for upgrade.'
365
+ );
366
+
367
+ $current = $this->mmb_get_transient('update_plugins');
368
+ $versions = array();
369
+ if(!empty($current)){
370
+ foreach($plugins as $plugin => $data){
371
+ if(isset($current->checked[$plugin])){
372
+ $versions[$current->checked[$plugin]] = $plugin;
373
+ }
374
+ }
375
+ }
376
+ $return = array();
377
+ if (class_exists('Plugin_Upgrader') && class_exists('Bulk_Plugin_Upgrader_Skin')) {
378
+ $upgrader = new Plugin_Upgrader(new Bulk_Plugin_Upgrader_Skin(compact('nonce', 'url')));
379
+ $result = $upgrader->bulk_upgrade(array_keys($plugins));
380
+ if (!function_exists('wp_update_plugins'))
381
+ include_once(ABSPATH . 'wp-includes/update.php');
382
+
383
+ @wp_update_plugins();
384
+ $current = $this->mmb_get_transient('update_plugins');
385
+ if (!empty($result)) {
386
+ foreach ($result as $plugin_slug => $plugin_info) {
387
+ if (!$plugin_info || is_wp_error($plugin_info)) {
388
+ $return[$plugin_slug] = $this->mmb_get_error($plugin_info);
389
+ } else {
390
+ if(!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)){
391
+ $return[$plugin_slug] = 1;
392
+ } else {
393
+ update_option('mmb_forcerefresh', true);
394
+ $return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
395
+ }
396
+ }
397
+ }
398
+ ob_end_clean();
399
+ return array(
400
+ 'upgraded' => $return
401
+ );
402
+ } else
403
+ return array(
404
+ 'error' => 'Upgrade failed.'
405
+ );
406
+ } else {
407
+ ob_end_clean();
408
+ return array(
409
+ 'error' => 'WordPress update required first.'
410
+ );
411
+ }
412
+ }
413
+
414
+ function upgrade_themes($themes = false)
415
+ {
416
+ if (!$themes || empty($themes))
417
+ return array(
418
+ 'error' => 'No theme files for upgrade.'
419
+ );
420
+
421
+ $current = $this->mmb_get_transient('update_themes');
422
+ $versions = array();
423
+ if(!empty($current)){
424
+ foreach($themes as $theme){
425
+ if(isset($current->checked[$theme])){
426
+ $versions[$current->checked[$theme]] = $theme;
427
+ }
428
+ }
429
+ }
430
+ if (class_exists('Theme_Upgrader') && class_exists('Bulk_Theme_Upgrader_Skin')) {
431
+ $upgrader = new Theme_Upgrader(new Bulk_Theme_Upgrader_Skin(compact('title', 'nonce', 'url', 'theme')));
432
+ $result = $upgrader->bulk_upgrade($themes);
433
+
434
+ if (!function_exists('wp_update_themes'))
435
+ include_once(ABSPATH . 'wp-includes/update.php');
436
+
437
+ @wp_update_themes();
438
+ $current = $this->mmb_get_transient('update_themes');
439
+ $return = array();
440
+ if (!empty($result)) {
441
+ foreach ($result as $theme_tmp => $theme_info) {
442
+ if (is_wp_error($theme_info) || empty($theme_info)) {
443
+ $return[$theme_tmp] = $this->mmb_get_error($theme_info);
444
+ } else {
445
+ if(!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)){
446
+ $return[$theme_tmp] = 1;
447
+ } else {
448
+ update_option('mmb_forcerefresh', true);
449
+ $return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
450
+ }
451
+ }
452
+ }
453
+ return array(
454
+ 'upgraded' => $return
455
+ );
456
+ } else
457
+ return array(
458
+ 'error' => 'Upgrade failed.'
459
+ );
460
+ } else {
461
+ ob_end_clean();
462
+ return array(
463
+ 'error' => 'WordPress update required first'
464
+ );
465
+ }
466
+ }
467
+
468
+ function upgrade_premium($premium = false)
469
+ {
470
+ global $mmb_plugin_url;
471
+
472
+ if (!class_exists('WP_Upgrader'))
473
+ include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
474
+
475
+ if (!$premium || empty($premium))
476
+ return array(
477
+ 'error' => 'No premium files for upgrade.'
478
+ );
479
+
480
+ $upgrader = false;
481
+ $pr_update = array();
482
+ $themes = array();
483
+ $plugins = array();
484
+ $result = array();
485
+ $premium_update = array();
486
+ $premium_update = apply_filters('mwp_premium_perform_update', $premium_update);
487
+ if (!empty($premium_update)) {
488
+
489
+ foreach ($premium as $pr) {
490
+ foreach ($premium_update as $key => $update) {
491
+ $update = array_change_key_case($update, CASE_LOWER);
492
+ if ($update['name'] == $pr['name']) {
493
+
494
+ // prepare bulk updates for premiums that use WordPress upgrader
495
+ if(isset($update['type'])){
496
+ if($update['type'] == 'plugin'){
497
+ if(isset($update['slug']) && !empty($update['slug']))
498
+ $plugins[$update['slug']] = $update;
499
+ }
500
+
501
+ if($update['type'] == 'theme'){
502
+ if(isset($update['template']) && !empty($update['template']))
503
+ $themes[$update['template']] = $update;
504
+ }
505
+ }
506
+ } else {
507
+ unset($premium_update[$key]);
508
+ }
509
+ }
510
+ }
511
+
512
+ // try default wordpress upgrader
513
+ if(!empty($plugins)){
514
+ $updateplugins = $this->upgrade_plugins(array_keys($plugins));
515
+ if(!empty($updateplugins) && isset($updateplugins['upgraded'])){
516
+ foreach ($premium_update as $key => $update) {
517
+ $update = array_change_key_case($update, CASE_LOWER);
518
+ foreach($updateplugins['upgraded'] as $slug => $upgrade){
519
+ if( isset($update['slug']) && $update['slug'] == $slug){
520
+ if( $upgrade == 1 )
521
+ unset($premium_update[$key]);
522
+
523
+ $pr_update['plugins']['upgraded'][md5($update['name'])] = $upgrade;
524
+ }
525
+ }
526
+ }
527
+ }
528
+ }
529
+
530
+ if(!empty($themes)){
531
+ $updatethemes = $this->upgrade_themes(array_keys($themes));
532
+ if(!empty($updatethemes) && isset($updatethemes['upgraded'])){
533
+ foreach ($premium_update as $key => $update) {
534
+ $update = array_change_key_case($update, CASE_LOWER);
535
+ foreach($updatethemes['upgraded'] as $template => $upgrade){
536
+ if( isset($update['template']) && $update['template'] == $template) {
537
+ if( $upgrade == 1 )
538
+ unset($premium_update[$key]);
539
+
540
+ $pr_update['themes']['upgraded'][md5($update['name'])] = $upgrade;
541
+ }
542
+ }
543
+ }
544
+ }
545
+ }
546
+
547
+ //try direct install with overwrite
548
+ if(!empty($premium_update)){
549
+ foreach ($premium_update as $update) {
550
+ $update = array_change_key_case($update, CASE_LOWER);
551
+ $update_result = false;
552
+ if (isset($update['url'])) {
553
+ if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
554
+ $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
555
+
556
+ $upgrader_skin = new WP_Upgrader_Skin();
557
+ $upgrader_skin->done_header = true;
558
+ $upgrader = new WP_Upgrader();
559
+ @$update_result = $upgrader->run(array(
560
+ 'package' => $update['url'],
561
+ 'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
562
+ 'clear_destination' => true,
563
+ 'clear_working' => true,
564
+ 'is_multi' => true,
565
+ 'hook_extra' => array()
566
+ ));
567
+ $update_result = !$update_result || is_wp_error($update_result) ? $this->mmb_get_error($update_result) : 1;
568
+
569
+ } else if (isset($update['callback'])) {
570
+ if (is_array($update['callback'])) {
571
+ $update_result = call_user_func(array( $update['callback'][0], $update['callback'][1] ));
572
+ } else if (is_string($update['callback'])) {
573
+ $update_result = call_user_func($update['callback']);
574
+ } else {
575
+ $update_result = 'Upgrade function "' . $update['callback'] . '" does not exists.';
576
+ }
577
+
578
+ $update_result = $update_result !== true ? $this->mmb_get_error($update_result) : 1;
579
+ } else
580
+ $update_result = 'Bad update params.';
581
+
582
+ $pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
583
+ }
584
+ }
585
+ return $pr_update;
586
+ } else {
587
+ foreach ($premium as $pr) {
588
+ $result[$pr['type'] . 's']['upgraded'][md5($pr['name'])] = 'This premium update is not registered.';
589
+ }
590
+ return $result;
591
+ }
592
+ }
593
+
594
+ function get_upgradable_plugins( $filter = array() )
595
+ {
596
+ $current = $this->mmb_get_transient('update_plugins');
597
+
598
+ $upgradable_plugins = array();
599
+ if (!empty($current->response)) {
600
+ if (!function_exists('get_plugin_data'))
601
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
602
+ foreach ($current->response as $plugin_path => $plugin_data) {
603
+ if ($plugin_path == 'worker/init.php')
604
+ continue;
605
+
606
+ $data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_path);
607
+ if(isset($data['Name']) && in_array($data['Name'], $filter))
608
+ continue;
609
+
610
+ if (strlen($data['Name']) > 0 && strlen($data['Version']) > 0) {
611
+ $current->response[$plugin_path]->name = $data['Name'];
612
+ $current->response[$plugin_path]->old_version = $data['Version'];
613
+ $current->response[$plugin_path]->file = $plugin_path;
614
+ unset($current->response[$plugin_path]->upgrade_notice);
615
+ $upgradable_plugins[] = $current->response[$plugin_path];
616
+ }
617
+ }
618
+ return $upgradable_plugins;
619
+ } else
620
+ return array();
621
+ }
622
+
623
+ function get_upgradable_themes( $filter = array() )
624
+ {
625
+ $all_themes = get_themes();
626
+ $upgrade_themes = array();
627
+
628
+ $current = $this->mmb_get_transient('update_themes');
629
+ if (!empty($current->response)) {
630
+ foreach ((array) $all_themes as $theme_template => $theme_data) {
631
+ if(isset($theme_data['Parent Theme']) && !empty($theme_data['Parent Theme']))
632
+ continue;
633
+
634
+ if(isset($theme_data['Name']) && in_array($theme_data['Name'], $filter))
635
+ continue;
636
+
637
+ foreach ($current->response as $current_themes => $theme) {
638
+ if ($theme_data['Template'] == $current_themes) {
639
+ if (strlen($theme_data['Name']) > 0 && strlen($theme_data['Version']) > 0) {
640
+ $current->response[$current_themes]['name'] = $theme_data['Name'];
641
+ $current->response[$current_themes]['old_version'] = $theme_data['Version'];
642
+ $current->response[$current_themes]['theme_tmp'] = $theme_data['Template'];
643
+ $upgrade_themes[] = $current->response[$current_themes];
644
+ }
645
+ }
646
+ }
647
+ }
648
+ }
649
+
650
+ return $upgrade_themes;
651
+ }
652
+
653
+ function get($args)
654
+ {
655
+ if (empty($args))
656
+ return false;
657
+
658
+ //Args: $items('plugins,'themes'), $type (active || inactive), $search(name string)
659
+
660
+ $return = array();
661
+ if (is_array($args['items']) && in_array('plugins', $args['items'])) {
662
+ $return['plugins'] = $this->get_plugins($args);
663
+ }
664
+ if (is_array($args['items']) && in_array('themes', $args['items'])) {
665
+ $return['themes'] = $this->get_themes($args);
666
+ }
667
+
668
+ return $return;
669
+ }
670
+
671
+ function get_plugins($args)
672
+ {
673
+ if (empty($args))
674
+ return false;
675
+
676
+ extract($args);
677
+
678
+ if (!function_exists('get_plugins')) {
679
+ include_once(ABSPATH . 'wp-admin/includes/plugin.php');
680
+ }
681
+ $all_plugins = get_plugins();
682
+ $plugins = array(
683
+ 'active' => array(),
684
+ 'inactive' => array()
685
+ );
686
+ if (is_array($all_plugins) && !empty($all_plugins)) {
687
+ $activated_plugins = get_option('active_plugins');
688
+ if (!$activated_plugins)
689
+ $activated_plugins = array();
690
+
691
+ $br_a = 0;
692
+ $br_i = 0;
693
+ foreach ($all_plugins as $path => $plugin) {
694
+ if ($plugin['Name'] != 'ManageWP - Worker') {
695
+ if (in_array($path, $activated_plugins)) {
696
+ $plugins['active'][$br_a]['path'] = $path;
697
+ $plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
698
+ $plugins['active'][$br_a]['version'] = $plugin['Version'];
699
+ $br_a++;
700
+ }
701
+
702
+ if (!in_array($path, $activated_plugins)) {
703
+ $plugins['inactive'][$br_i]['path'] = $path;
704
+ $plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
705
+ $plugins['inactive'][$br_i]['version'] = $plugin['Version'];
706
+ $br_i++;
707
+ }
708
+
709
+ }
710
+
711
+ if ($search) {
712
+ foreach ($plugins['active'] as $k => $plugin) {
713
+ if (!stristr($plugin['name'], $search)) {
714
+ unset($plugins['active'][$k]);
715
+ }
716
+ }
717
+
718
+ foreach ($plugins['inactive'] as $k => $plugin) {
719
+ if (!stristr($plugin['name'], $search)) {
720
+ unset($plugins['inactive'][$k]);
721
+ }
722
+ }
723
+ }
724
+ }
725
+ }
726
+
727
+ return $plugins;
728
+ }
729
+
730
+ function get_themes($args)
731
+ {
732
+ if (empty($args))
733
+ return false;
734
+
735
+ extract($args);
736
+
737
+ if (!function_exists('get_themes')) {
738
+ include_once(ABSPATH . WPINC . '/theme.php');
739
+ }
740
+ $all_themes = get_themes();
741
+ $themes = array(
742
+ 'active' => array(),
743
+ 'inactive' => array()
744
+ );
745
+
746
+ if (is_array($all_themes) && !empty($all_themes)) {
747
+ $current_theme = get_current_theme();
748
+
749
+ $br_a = 0;
750
+ $br_i = 0;
751
+ foreach ($all_themes as $theme_name => $theme) {
752
+ if ($current_theme == $theme_name) {
753
+ $themes['active'][$br_a]['path'] = $theme['Template'];
754
+ $themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
755
+ $themes['active'][$br_a]['version'] = $theme['Version'];
756
+ $themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
757
+ $br_a++;
758
+ }
759
+
760
+ if ($current_theme != $theme_name) {
761
+ $themes['inactive'][$br_i]['path'] = $theme['Template'];
762
+ $themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
763
+ $themes['inactive'][$br_i]['version'] = $theme['Version'];
764
+ $themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
765
+ $br_i++;
766
+ }
767
+
768
+ }
769
+
770
+ if ($search) {
771
+ foreach ($themes['active'] as $k => $theme) {
772
+ if (!stristr($theme['name'], $search)) {
773
+ unset($themes['active'][$k]);
774
+ }
775
+ }
776
+
777
+ foreach ($themes['inactive'] as $k => $theme) {
778
+ if (!stristr($theme['name'], $search)) {
779
+ unset($themes['inactive'][$k]);
780
+ }
781
+ }
782
+ }
783
+ }
784
+
785
+ return $themes;
786
+ }
787
+
788
+ function edit($args)
789
+ {
790
+ extract($args);
791
+ $return = array();
792
+ if ($type == 'plugins') {
793
+ $return['plugins'] = $this->edit_plugins($args);
794
+ } elseif ($type == 'themes') {
795
+ $return['themes'] = $this->edit_themes($args);
796
+ }
797
+ return $return;
798
+ }
799
+
800
+ function edit_plugins($args)
801
+ {
802
+ extract($args);
803
+ $return = array();
804
+ foreach ($items as $item) {
805
+ switch ($items_edit_action) {
806
+ case 'activate':
807
+ $result = activate_plugin($item['path']);
808
+ break;
809
+ case 'deactivate':
810
+ $result = deactivate_plugins(array(
811
+ $item['path']
812
+ ));
813
+ break;
814
+ case 'delete':
815
+ $result = delete_plugins(array(
816
+ $item['path']
817
+ ));
818
+ break;
819
+ default:
820
+ break;
821
+ }
822
+
823
+ if (is_wp_error($result)) {
824
+ $result = array(
825
+ 'error' => $result->get_error_message()
826
+ );
827
+ } elseif ($result === false) {
828
+ $result = array(
829
+ 'error' => "Failed to perform action."
830
+ );
831
+ } else {
832
+ $result = "OK";
833
+ }
834
+ $return[$item['name']] = $result;
835
+ }
836
+
837
+ return $return;
838
+ }
839
+
840
+ function edit_themes($args)
841
+ {
842
+ extract($args);
843
+ $return = array();
844
+ foreach ($items as $item) {
845
+ switch ($items_edit_action) {
846
+ case 'activate':
847
+ switch_theme($item['path'], $item['stylesheet']);
848
+ break;
849
+ case 'delete':
850
+ $result = delete_theme($item['path']);
851
+ break;
852
+ default:
853
+ break;
854
+ }
855
+
856
+ if (is_wp_error($result)) {
857
+ $result = array(
858
+ 'error' => $result->get_error_message()
859
+ );
860
+ } elseif ($result === false) {
861
+ $result = array(
862
+ 'error' => "Failed to perform action."
863
+ );
864
+ } else {
865
+ $result = "OK";
866
+ }
867
+ $return[$item['name']] = $result;
868
+ }
869
+
870
+ return $return;
871
+
872
+ }
873
+ }
874
  ?>
lib/dropbox.oauth.php CHANGED
@@ -1,1134 +1,1134 @@
1
- <?php
2
-
3
- /**
4
- * Dropbox class
5
- *
6
- * This source file can be used to communicate with Dropbox (http://dropbox.com)
7
- *
8
- * The class is documented in the file itself. If you find any bugs help me out and report them. Reporting can be done by sending an email to php-dropbox-bugs[at]verkoyen[dot]eu.
9
- * If you report a bug, make sure you give me enough information (include your code).
10
- *
11
- * Changelog since 1.0.4
12
- * - Fixed filesPost so it returns a boolean.
13
- * - Some code styling
14
- *
15
- * Changelog since 1.0.3
16
- * - Corrected the authorize-URL (thx to Jacob Budin).
17
- *
18
- * Changelog since 1.0.2
19
- * - Added methods to enable oauth-usage.
20
- *
21
- * Changelog since 1.0.1
22
- * - Bugfix: when doing multiple calles where GET and POST is mixed, the postfields should be reset (thx to Daniel Hトてスsken)
23
- *
24
- * Changelog since 1.0.0
25
- * - fixed some issues with generation off the basestring
26
- *
27
- * License
28
- * Copyright (c), Tijs Verkoyen. All rights reserved.
29
- *
30
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
31
- *
32
- * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
33
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
34
- * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
35
- *
36
- * This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
37
- *
38
- * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
39
- * @version 1.0.5
40
- *
41
- * @copyright Copyright (c), Tijs Verkoyen. All rights reserved.
42
- * @license BSD License
43
- */
44
- class Dropbox
45
- {
46
- // internal constant to enable/disable debugging
47
- const DEBUG = false;
48
-
49
- // url for the dropbox-api
50
- const API_URL = 'https://api.dropbox.com';
51
- const API_AUTH_URL = 'https://www.dropbox.com';
52
- const API_CONTENT_URL = 'https://api-content.dropbox.com';
53
-
54
- // port for the dropbox-api
55
- const API_PORT = 443;
56
-
57
- // current version
58
- const VERSION = '1.0.5';
59
-
60
-
61
- /**
62
- * A cURL instance
63
- *
64
- * @var resource
65
- */
66
- private $curl;
67
-
68
-
69
- /**
70
- * The application key
71
- *
72
- * @var string
73
- */
74
- private $applicationKey;
75
-
76
-
77
- /**
78
- * The application secret
79
- *
80
- * @var string
81
- */
82
- private $applicationSecret;
83
-
84
-
85
- /**
86
- * The oAuth-token
87
- *
88
- * @var string
89
- */
90
- private $oAuthToken = '';
91
-
92
-
93
- /**
94
- * The oAuth-token-secret
95
- *
96
- * @var string
97
- */
98
- private $oAuthTokenSecret = '';
99
-
100
-
101
- /**
102
- * The timeout
103
- *
104
- * @var int
105
- */
106
- private $timeOut = 60;
107
-
108
-
109
- /**
110
- * The user agent
111
- *
112
- * @var string
113
- */
114
- private $userAgent;
115
-
116
-
117
- // class methods
118
- /**
119
- * Default constructor
120
- *
121
- * @return void
122
- * @param string $applicationKey The application key to use.
123
- * @param string $applicationSecret The application secret to use.
124
- */
125
- public function __construct($applicationKey, $applicationSecret)
126
- {
127
- $this->setApplicationKey($applicationKey);
128
- $this->setApplicationSecret($applicationSecret);
129
- }
130
-
131
-
132
- /**
133
- * Default destructor
134
- *
135
- * @return void
136
- */
137
- public function __destruct()
138
- {
139
- if($this->curl != null) curl_close($this->curl);
140
- }
141
-
142
-
143
- /**
144
- * Format the parameters as a querystring
145
- *
146
- * @return string
147
- * @param array $parameters The parameters to pass.
148
- */
149
- private function buildQuery(array $parameters)
150
- {
151
- // no parameters?
152
- if(empty($parameters)) return '';
153
-
154
- // encode the keys
155
- $keys = self::urlencode_rfc3986(array_keys($parameters));
156
-
157
- // encode the values
158
- $values = self::urlencode_rfc3986(array_values($parameters));
159
-
160
- // reset the parameters
161
- $parameters = array_combine($keys, $values);
162
-
163
- // sort parameters by key
164
- uksort($parameters, 'strcmp');
165
-
166
- // loop parameters
167
- foreach($parameters as $key => $value)
168
- {
169
- // sort by value
170
- if(is_array($value)) $parameters[$key] = natsort($value);
171
- }
172
-
173
- // process parameters
174
- foreach($parameters as $key => $value) $chunks[] = $key . '=' . str_replace('%25', '%', $value);
175
-
176
- // return
177
- return implode('&', $chunks);
178
- }
179
-
180
-
181
- /**
182
- * All OAuth 1.0 requests use the same basic algorithm for creating a signature base string and a signature.
183
- * The signature base string is composed of the HTTP method being used, followed by an ampersand ("&") and then the URL-encoded base URL being accessed,
184
- * complete with path (but not query parameters), followed by an ampersand ("&").
185
- * Then, you take all query parameters and POST body parameters (when the POST body is of the URL-encoded type, otherwise the POST body is ignored),
186
- * including the OAuth parameters necessary for negotiation with the request at hand, and sort them in lexicographical order by first parameter name and
187
- * then parameter value (for duplicate parameters), all the while ensuring that both the key and the value for each parameter are URL encoded in isolation.
188
- * Instead of using the equals ("=") sign to mark the key/value relationship, you use the URL-encoded form of "%3D". Each parameter is then joined by the
189
- * URL-escaped ampersand sign, "%26".
190
- *
191
- * @return string
192
- * @param string $url The url to use.
193
- * @param string $method The method that will be called.
194
- * @param array $parameters The parameters to pass.
195
- */
196
- private function calculateBaseString($url, $method, array $parameters)
197
- {
198
- // redefine
199
- $url = (string) $url;
200
- $parameters = (array) $parameters;
201
-
202
- // init var
203
- $pairs = array();
204
- $chunks = array();
205
-
206
- // sort parameters by key
207
- uksort($parameters, 'strcmp');
208
-
209
- // loop parameters
210
- foreach($parameters as $key => $value)
211
- {
212
- // sort by value
213
- if(is_array($value)) $parameters[$key] = natsort($value);
214
- }
215
-
216
- // process queries
217
- foreach($parameters as $key => $value)
218
- {
219
- // only add if not already in the url
220
- if(substr_count($url, $key . '=' . $value) == 0) $chunks[] = self::urlencode_rfc3986($key) . '%3D' . self::urlencode_rfc3986($value);
221
- }
222
-
223
- $urlChunks = explode('/', $url);
224
- $i = 0;
225
-
226
- foreach($urlChunks as &$chunk)
227
- {
228
- if($i > 4) $chunk = self::urlencode_rfc3986($chunk);
229
- else $chunk = urlencode($chunk);
230
-
231
- $i++;
232
-
233
- }
234
-
235
- // build base
236
- $base = $method . '&';
237
- $base .= implode('%2F', $urlChunks);
238
- $base .= (substr_count($url, '?')) ? '%26' : '&';
239
- $base .= implode('%26', $chunks);
240
- $base = str_replace(array('%3F', '%20'), array('&', '%2520'), $base);
241
-
242
- // return
243
- return $base;
244
- }
245
-
246
-
247
- /**
248
- * Build the Authorization header
249
- * @later: fix me
250
- *
251
- * @return string
252
- * @param array $parameters The parameters to pass.
253
- * @param string $url The url to use.
254
- */
255
- private function calculateHeader(array $parameters, $url)
256
- {
257
- // redefine
258
- $url = (string) $url;
259
-
260
- // divide into parts
261
- $parts = parse_url($url);
262
-
263
- // init var
264
- $chunks = array();
265
-
266
- // process queries
267
- foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', self::urlencode_rfc3986($key) . '="' . self::urlencode_rfc3986($value) . '"');
268
- $parts['path']=str_replace("%2F", "/", rawurlencode($parts['path']));
269
- // build return
270
- $return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
271
- $return .= implode(',', $chunks);
272
- // prepend name and OAuth part
273
- return $return;
274
- }
275
-
276
-
277
- /**
278
- * Make an call to the oAuth
279
- * @todo refactor me
280
- *
281
- * @return array
282
- * @param string $url The url that has to be called.
283
- * @param array[optional] $parameters The parameters to pass.
284
- * @param string[optional] $method Which HTTP-method should we use? Possible values are POST, GET.
285
- * @param bool[optional] $expectJSON Do we expect JSON?
286
- */
287
- private function doOAuthCall($url, array $parameters = null, $method = 'POST', $expectJSON = true)
288
- {
289
- // redefine
290
- $url = (string) $url;
291
-
292
- // append default parameters
293
- $parameters['oauth_consumer_key'] = $this->getApplicationKey();
294
- $parameters['oauth_nonce'] = md5(microtime() . rand());
295
- $parameters['oauth_timestamp'] = time();
296
- $parameters['oauth_signature_method'] = 'HMAC-SHA1';
297
- $parameters['oauth_version'] = '1.0';
298
-
299
- // calculate the base string
300
- $base = $this->calculateBaseString(self::API_URL . '/' . $url, 'POST', $parameters);
301
-
302
- // add sign into the parameters
303
- $parameters['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
304
-
305
- // calculate header
306
- $header = $this->calculateHeader($parameters, self::API_URL . '/' . $url);
307
-
308
- if($method == 'POST')
309
- {
310
- $options[CURLOPT_POST] = true;
311
- $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
312
- }
313
-
314
- else
315
- {
316
- // reset post
317
- $options[CURLOPT_POST] = 0;
318
- unset($options[CURLOPT_POSTFIELDS]);
319
-
320
- // add the parameters into the querystring
321
- if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
322
- }
323
-
324
- // set options
325
- $options[CURLOPT_URL] = self::API_URL . '/' . $url;
326
- $options[CURLOPT_PORT] = self::API_PORT;
327
- $options[CURLOPT_USERAGENT] = $this->getUserAgent();
328
- if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
329
- $options[CURLOPT_RETURNTRANSFER] = true;
330
- $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
331
- $options[CURLOPT_SSL_VERIFYPEER] = false;
332
- $options[CURLOPT_SSL_VERIFYHOST] = false;
333
- $options[CURLOPT_HTTPHEADER] = array('Expect:');
334
-
335
- // init
336
- $this->curl = curl_init();
337
-
338
- // set options
339
- curl_setopt_array($this->curl, $options);
340
-
341
- // execute
342
- $response = curl_exec($this->curl);
343
- $headers = curl_getinfo($this->curl);
344
-
345
- // fetch errors
346
- $errorNumber = curl_errno($this->curl);
347
- $errorMessage = curl_error($this->curl);
348
-
349
- // error?
350
- if($errorNumber != '') throw new DropboxException($errorMessage, $errorNumber);
351
-
352
- // return
353
- if($expectJSON) return json_decode($response, true);
354
-
355
- // fallback
356
- return $response;
357
- }
358
-
359
-
360
- /**
361
- * Make the call
362
- *
363
- * @return string
364
- * @param string $url The url to call.
365
- * @param array[optional] $parameters Optional parameters.
366
- * @param bool[optional] $method The method to use. Possible values are GET, POST.
367
- * @param string[optional] $filePath The path to the file to upload.
368
- * @param bool[optional] $expectJSON Do we expect JSON?
369
- * @param bool[optional] $isContent Is this content?
370
- */
371
- private function doCall($url, array $parameters = null, $method = 'GET', $filePath = null, $expectJSON = true, $isContent = false)
372
- {
373
- // allowed methods
374
- $allowedMethods = array('GET', 'POST');
375
-
376
- // redefine
377
- $url = (string) $url;
378
- $parameters = (array) $parameters;
379
- $method = (string) $method;
380
- $expectJSON = (bool) $expectJSON;
381
-
382
- // validate method
383
- if(!in_array($method, $allowedMethods)) throw new DropboxException('Unknown method (' . $method . '). Allowed methods are: ' . implode(', ', $allowedMethods));
384
-
385
- // append default parameters
386
- $oauth['oauth_consumer_key'] = $this->getApplicationKey();
387
- $oauth['oauth_nonce'] = md5(microtime() . rand());
388
- $oauth['oauth_timestamp'] = time();
389
- $oauth['oauth_token'] = $this->getOAuthToken();
390
- $oauth['oauth_signature_method'] = 'HMAC-SHA1';
391
- $oauth['oauth_version'] = '1.0';
392
-
393
- // set data
394
- $data = $oauth;
395
- if(!empty($parameters))
396
- {
397
- // convert to UTF-8
398
- foreach($parameters as &$value) $value = utf8_encode($value);
399
-
400
- // merge
401
- $data = array_merge($data, $parameters);
402
- }
403
-
404
- if($filePath != null)
405
- {
406
- // process file
407
- $fileInfo = pathinfo($filePath);
408
-
409
- // add to the data
410
- $data['file'] = $fileInfo['basename'];
411
-
412
- }
413
-
414
- // calculate the base string
415
- if($isContent) $base = $this->calculateBaseString(self::API_CONTENT_URL . '/' . $url, $method, $data);
416
- else $base = $this->calculateBaseString(self::API_URL . '/' . $url, $method, $data);
417
-
418
- // based on the method, we should handle the parameters in a different way
419
- if($method == 'POST')
420
- {
421
- // file provided?
422
- if($filePath != null)
423
- {
424
- // build a boundary
425
- $boundary = md5(time());
426
-
427
- // init var
428
- $content = '--' . $boundary . "\r\n";
429
-
430
- // set file
431
- $content .= 'Content-Disposition: form-data; name=file; filename="' . $fileInfo['basename'] . '"' . "\r\n";
432
- $content .= 'Content-Type: application/octet-stream' . "\r\n";
433
- $content .= "\r\n";
434
- $content .= file_get_contents($filePath);
435
- $content .= "\r\n";
436
- $content .= "--" . $boundary . '--';
437
-
438
- // build headers
439
- $headers[] = 'Content-Type: multipart/form-data; boundary=' . $boundary;
440
- $headers[] = 'Content-Length: ' . strlen($content);
441
-
442
- // set content
443
- $options[CURLOPT_POSTFIELDS] = $content;
444
- }
445
-
446
- // no file
447
- else $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
448
-
449
- // enable post
450
- $options[CURLOPT_POST] = 1;
451
- }
452
-
453
- else
454
- {
455
- // reset post
456
- $options[CURLOPT_POST] = 0;
457
- unset($options[CURLOPT_POSTFIELDS]);
458
- $url=str_replace("%2F", "/", rawurlencode($url));
459
-
460
- // add the parameters into the querystring
461
- if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
462
- }
463
-
464
- // add sign into the parameters
465
- $oauth['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
466
-
467
- if($isContent) $headers[] = $this->calculateHeader($oauth, self::API_CONTENT_URL . '/' . $url);
468
- else $headers[] = $this->calculateHeader($oauth, self::API_URL . '/' . $url);
469
- $headers[] = 'Expect:';
470
-
471
- // set options
472
- if($isContent) $options[CURLOPT_URL] = self::API_CONTENT_URL . '/' . $url;
473
- else $options[CURLOPT_URL] = self::API_URL . '/' . $url;
474
- $options[CURLOPT_PORT] = self::API_PORT;
475
- $options[CURLOPT_USERAGENT] = $this->getUserAgent();
476
- if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
477
- $options[CURLOPT_RETURNTRANSFER] = true;
478
- $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
479
- $options[CURLOPT_SSL_VERIFYPEER] = false;
480
- $options[CURLOPT_SSL_VERIFYHOST] = false;
481
- $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
482
- $options[CURLOPT_HTTPHEADER] = $headers;
483
- // init
484
- if($this->curl == null) $this->curl = curl_init();
485
-
486
- // set options
487
- curl_setopt_array($this->curl, $options);
488
-
489
- // execute
490
- $response = curl_exec($this->curl);
491
- $headers = curl_getinfo($this->curl);
492
-
493
- // fetch errors
494
- $errorNumber = curl_errno($this->curl);
495
- $errorMessage = curl_error($this->curl);
496
-
497
- if(!$expectJSON && $isContent)
498
- {
499
- // is it JSON?
500
- $json = @json_decode($response, true);
501
- if($json !== false && isset($json['error'])) throw new DropboxException($json['error']);
502
-
503
- // set return
504
- $return['content_type'] = $headers['content_type'];
505
- $return['data'] = base64_encode($response);
506
-
507
- // return
508
- return $return;
509
- }
510
-
511
- // we don't expect JSON, return the response
512
- if(!$expectJSON) return $response;
513
-
514
- // replace ids with their string values, added because of some PHP-version can't handle these large values
515
- $response = preg_replace('/id":(\d+)/', 'id":"\1"', $response);
516
-
517
- // we expect JSON, so decode it
518
- $json = @json_decode($response, true);
519
-
520
- // validate JSON
521
- if($json === null)
522
- {
523
- // should we provide debug information
524
- if(self::DEBUG)
525
- {
526
- // make it output proper
527
- echo '<pre>';
528
-
529
- // dump the header-information
530
- var_dump($headers);
531
-
532
- // dump the error
533
- var_dump($errorMessage);
534
-
535
- // dump the raw response
536
- var_dump($response);
537
-
538
- // end proper format
539
- echo '</pre>';
540
- }
541
-
542
- // throw exception
543
- throw new DropboxException('Invalid response.');
544
- }
545
-
546
- // any error
547
- if(isset($json['error']))
548
- {
549
- // should we provide debug information
550
- if(self::DEBUG)
551
- {
552
- // make it output proper
553
- echo '<pre>';
554
-
555
- // dump the header-information
556
- var_dump($headers);
557
-
558
- // dump the raw response
559
- var_dump($response);
560
-
561
- // end proper format
562
- echo '</pre>';
563
- }
564
-
565
- if(isset($json['error']) && is_string($json['error'])) $message = $json['error'];
566
- elseif(isset($json['error']['hash']) && $json['error']['hash'] != '') $message = (string) $json['error']['hash'];
567
- else $message = 'Invalid response.';
568
-
569
- // throw exception
570
- throw new DropboxException($message);
571
- }
572
-
573
- // return
574
- return $json;
575
- }
576
-
577
-
578
- /**
579
- * Get the application key
580
- *
581
- * @return string
582
- */
583
- private function getApplicationKey()
584
- {
585
- return $this->applicationKey;
586
- }
587
-
588
-
589
- /**
590
- * Get the application secret
591
- *
592
- * @return string
593
- */
594
- private function getApplicationSecret()
595
- {
596
- return $this->applicationSecret;
597
- }
598
-
599
-
600
- /**
601
- * Get the oAuth-token
602
- *
603
- * @return string
604
- */
605
- private function getOAuthToken()
606
- {
607
- return $this->oAuthToken;
608
- }
609
-
610
-
611
- /**
612
- * Get the oAuth-token-secret
613
- *
614
- * @return string
615
- */
616
- private function getOAuthTokenSecret()
617
- {
618
- return $this->oAuthTokenSecret;
619
- }
620
-
621
-
622
- /**
623
- * Get the timeout
624
- *
625
- * @return int
626
- */
627
- public function getTimeOut()
628
- {
629
- return (int) $this->timeOut;
630
- }
631
-
632
-
633
- /**
634
- * Get the useragent that will be used. Our version will be prepended to yours.
635
- * It will look like: "PHP Dropbox/<version> <your-user-agent>"
636
- *
637
- * @return string
638
- */
639
- public function getUserAgent()
640
- {
641
- return (string) 'PHP Dropbox/' . self::VERSION . ' ' . $this->userAgent;
642
- }
643
-
644
-
645
- /**
646
- * Set the application key
647
- *
648
- * @return void
649
- * @param string $key The application key to use.
650
- */
651
- private function setApplicationKey($key)
652
- {
653
- $this->applicationKey = (string) $key;
654
- }
655
-
656
-
657
- /**
658
- * Set the application secret
659
- *
660
- * @return void
661
- * @param string $secret The application secret to use.
662
- */
663
- private function setApplicationSecret($secret)
664
- {
665
- $this->applicationSecret = (string) $secret;
666
- }
667
-
668
-
669
- /**
670
- * Set the oAuth-token
671
- *
672
- * @return void
673
- * @param string $token The token to use.
674
- */
675
- public function setOAuthToken($token)
676
- {
677
- $this->oAuthToken = (string) $token;
678
- }
679
-
680
-
681
- /**
682
- * Set the oAuth-secret
683
- *
684
- * @return void
685
- * @param string $secret The secret to use.
686
- */
687
- public function setOAuthTokenSecret($secret)
688
- {
689
- $this->oAuthTokenSecret = (string) $secret;
690
- }
691
-
692
-
693
- /**
694
- * Set the timeout
695
- *
696
- * @return void
697
- * @param int $seconds The timeout in seconds.
698
- */
699
- public function setTimeOut($seconds)
700
- {
701
- $this->timeOut = (int) $seconds;
702
- }
703
-
704
-
705
- /**
706
- * Get the useragent that will be used. Our version will be prepended to yours.
707
- * It will look like: "PHP Dropbox/<version> <your-user-agent>"
708
- *
709
- * @return void
710
- * @param string $userAgent Your user-agent, it should look like <app-name>/<app-version>.
711
- */
712
- public function setUserAgent($userAgent)
713
- {
714
- $this->userAgent = (string) $userAgent;
715
- }
716
-
717
-
718
- /**
719
- * Build the signature for the data
720
- *
721
- * @return string
722
- * @param string $key The key to use for signing.
723
- * @param string $data The data that has to be signed.
724
- */
725
- private function hmacsha1($key, $data)
726
- {
727
- return base64_encode(hash_hmac('SHA1', $data, $key, true));
728
- }
729
-
730
-
731
- /**
732
- * URL-encode method for internatl use
733
- *
734
- * @return string
735
- * @param mixed $value The value to encode.
736
- */
737
- private static function urlencode_rfc3986($value)
738
- {
739
- if(is_array($value)) return array_map(array('Dropbox', 'urlencode_rfc3986'), $value);
740
- else
741
- {
742
- $search = array('+', ' ', '%7E', '%');
743
- $replace = array('%20', '%20', '~', '%25');
744
-
745
- return str_replace($search, $replace, rawurlencode($value));
746
- }
747
- }
748
-
749
-
750
- // oauth resources
751
- /**
752
- * Call for obtaining an OAuth request token.
753
- * Returns a request token and the corresponding request token secret. This token and secret cannot be used to sign requests for the /metadata and /file content API calls.
754
- * Their only purpose is for signing a request to oauth/access_token once the user has gone through the application authorization steps provided by oauth/authorize.
755
- *
756
- * @return array
757
- */
758
- public function oAuthRequestToken()
759
- {
760
- // make the call
761
- $response = $this->doOAuthCall('1/oauth/request_token', null, 'POST', false);
762
-
763
- // process response
764
- $response = (array) explode('&', $response);
765
- $return = array();
766
-
767
- // loop chunks
768
- foreach($response as $chunk)
769
- {
770
- // split again
771
- $chunks = explode('=', $chunk, 2);
772
-
773
- // store return
774
- if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
775
- }
776
-
777
- // return
778
- return $return;
779
- }
780
-
781
-
782
- /**
783
- * Redirect the user to the oauth/authorize location so that Dropbox can authenticate the user and ask whether or not the user wants to authorize the application to access
784
- * file metadata and content on its behalf. oauth/authorize is not an API call per se, because it does not have a return value, but rather directs the user to a page on
785
- * api.dropbox.com where they are provided means to log in to Dropbox and grant authority to the application requesting it.
786
- * The page served by oauth/authorize should be presented to the user through their web browser.
787
- * Please note, without directing the user to a Dropbox-provided page via oauth/authorize, it is impossible for your application to use the request token it received
788
- * via oauth/request_token to obtain an access token from oauth/access_token.
789
- *
790
- * @return void
791
- * @param string $oauthToken The request token of the application requesting authority from a user.
792
- * @param string[optional] $oauthCallback After the user authorizes an application, the user is redirected to the application-served URL provided by this parameter.
793
- */
794
- public function oAuthAuthorize($oauthToken, $oauthCallback = null)
795
- {
796
- // build parameters
797
- $parameters = array();
798
- $parameters['oauth_token'] = (string) $oauthToken;
799
- if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
800
-
801
- // build url
802
- $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
803
-
804
- // redirect
805
- header('Location: ' . $url);
806
- exit;
807
- }
808
-
809
- public function mwp_oAuthAuthorize($oauthToken, $oauthCallback = null)
810
- {
811
- // build parameters
812
- $parameters = array();
813
- $parameters['oauth_token'] = (string) $oauthToken;
814
- if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
815
-
816
- // build url
817
- $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
818
-
819
- return $url;
820
- }
821
-
822
- /**
823
- * This call returns a access token and the corresponding access token secret.
824
- * Upon return, the authorization process is now complete and the access token and corresponding secret are used to sign requests for the metadata and file content API calls.
825
- *
826
- * @return array
827
- * @param string $oauthToken The token returned after authorizing.
828
- */
829
- public function oAuthAccessToken($oauthToken)
830
- {
831
- // build parameters
832
- $parameters = array();
833
- $parameters['oauth_token'] = (string) $oauthToken;
834
-
835
- // make the call
836
- $response = $this->doOAuthCall('1/oauth/access_token', $parameters, 'POST', false);
837
-
838
- // process response
839
- $response = (array) explode('&', $response);
840
- $return = array();
841
-
842
- // loop chunks
843
- foreach($response as $chunk)
844
- {
845
- // split again
846
- $chunks = explode('=', $chunk, 2);
847
-
848
- // store return
849
- if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
850
- }
851
-
852
- // return
853
- return $return;
854
- }
855
-
856
-
857
- // token resources
858
- /**
859
- * The token call provides a consumer/secret key pair you can use to consistently access the user's account.
860
- * This is the preferred method of authentication over storing the username and password.
861
- * Use the key pair as a signature with every subsequent call.
862
- * The request must be signed using the application's developer and secret key token. Request or access tokens are necessary.
863
- *
864
- * Warning: DO NOT STORE THE USER'S PASSWORD! The way this call works is you call it once with the user's email and password and then
865
- * keep the token around for later. You do NOT (I repeat NOT) call this before everything you do or on each program startup.
866
- * We watch for this and will shut down your application with little notice if we catch you.
867
- * In fact, the Objective-C code does this for you so you can't get it wrong.
868
- *
869
- * @return array Upon successful verification of the user's credentials, returns an array representation of the access token and secret.
870
- * @param string $email The email account of the user.
871
- * @param string $password The password of the user.
872
- */
873
- public function token($email, $password)
874
- {
875
- // build parameters
876
- $parameters = array();
877
- $parameters['email'] = (string) $email;
878
- $parameters['password'] = (string) $password;
879
-
880
- // make the call
881
- $response = (array) $this->doOAuthCall('1/token', $parameters);
882
-
883
- // validate and set
884
- if(isset($response['token'])) $this->setOAuthToken($response['token']);
885
- if(isset($response['secret'])) $this->setOAuthTokenSecret($response['secret']);
886
-
887
- // return
888
- return $response;
889
- }
890
-
891
-
892
- // account resources
893
- /**
894
- * Given a set of account information, the account call allows an application to create a new Dropbox user account.
895
- * This is useful for situations where the trusted third party application is possibly the user's first interaction with Dropbox.
896
- *
897
- * @return bool
898
- * @param string $email The email account of the user.
899
- * @param string $password The password for the user.
900
- * @param string $firstName The user's first name.
901
- * @param string $lastName The user's last name.
902
- */
903
- public function account($email, $password, $firstName, $lastName)
904
- {
905
- // build parameters
906
- $parameters['email'] = (string) $email;
907
- $parameters['first_name'] = (string) $firstName;
908
- $parameters['last_name'] = (string) $lastName;
909
- $parameters['password'] = (string) $password;
910
-
911
- return (bool) ($this->doCall('1/account', $parameters, 'POST', null, false) == 'OK');
912
- }
913
-
914
-
915
- /**
916
- * Get the user account information.
917
- *
918
- * @return array
919
- */
920
- public function accountInfo()
921
- {
922
- // make the call
923
- return (array) $this->doCall('1/account/info');
924
- }
925
-
926
-
927
- // files & metadata
928
- /**
929
- * Retrieves file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
930
- *
931
- * @return string
932
- * @param string $path Path of the directory wherin the file is located.
933
- * @param bool[optional] $sandbox Sandbox mode?
934
- */
935
- public function filesGet($path, $sandbox = false)
936
- {
937
- // build url
938
- $url = '1/files/';
939
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
940
- $url .= trim((string) $path, '/');
941
-
942
- // make the call
943
- return $this->doCall($url, null, 'GET', null, false, true);
944
- }
945
-
946
-
947
- /**
948
- * Uploads file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
949
- *
950
- * @return bool
951
- * @param string $path Path of the directory wherin the file should be uploaded.
952
- * @param string $localFile Path to the local file.
953
- * @param bool[optional] $sandbox Sandbox mode?
954
- */
955
- public function filesPost($path, $localFile, $sandbox = false)
956
- {
957
- // build url
958
- $url = '1/files/';
959
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
960
- $url .= trim((string) $path, '/');
961
-
962
- // make the call
963
- $return = $this->doCall($url, null, 'POST', $localFile, true, true);
964
- // return the result
965
- return (bool) (isset($return['size']) && $return['size'] == 'winner!');
966
- }
967
-
968
-
969
- /**
970
- * Returns metadata for the file or directory at the given <path> location relative to the user's Dropbox or
971
- * the user's application sandbox. If <path> represents a directory and the list parameter is true, the metadata will
972
- * also include a listing of metadata for the directory's contents.
973
- *
974
- * @return array
975
- * @param string[optional] $path The path to the file/director to get the metadata for.
976
- * @param int[optional] $fileLimit When listing a directory, the service will not report listings containing more than $fileLimit files.
977
- * @param bool[optional] $hash Listing return values include a hash representing the state of the directory's contents.
978
- * @param bool[optional] $list If true, this call returns a list of metadata representations for the contents of the directory. If false, this call returns the metadata for the directory itself.
979
- * @param bool[optional] $sandbox Sandbox mode?
980
- */
981
- public function metadata($path = '', $fileLimit = 10000, $hash = false, $list = true, $sandbox = false)
982
- {
983
- // build url
984
- $url = '1/metadata/';
985
- $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
986
- $url .= trim((string) $path, '/');
987
-
988
- // build parameters
989
- $parameters = null;
990
- $parameters['file_limit'] = (int) $fileLimit;
991
- if((bool) $hash) $parameters['hash'] = '';
992
- $parameters['list'] = ($list) ? 'true': 'false';
993
-
994
- // make the call
995
- return (array) $this->doCall($url, $parameters);
996
- }
997
-
998
-
999
- /**
1000
- * Get a minimized thumbnail for a photo.
1001
- *
1002
- * @return string Will return a base64_encode string with the JPEG-data
1003
- * @param string $path The path to the photo.
1004
- * @param string[optional] $size The size, possible values are: 'small' (32x32), 'medium' (64x64), 'large' (128x128).
1005
- */
1006
- public function thumbnails($path, $size = 'small')
1007
- {
1008
- // build url
1009
- $url = '1/thumbnails/dropbox/';
1010
- $url .= trim((string) $path, '/');
1011
-
1012
- // build parameters
1013
- $parameters['size'] = (string) $size;
1014
-
1015
- // make the call
1016
- return $this->doCall($url, $parameters, 'GET', null, false, true);
1017
- }
1018
-
1019
-
1020
- // file operations
1021
- /**
1022
- * Copy a file or folder to a new location.
1023
- *
1024
- * @return array
1025
- * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1026
- * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1027
- * @param bool[optional] $sandbox Sandbox mode?
1028
- */
1029
- public function fileopsCopy($fromPath, $toPath, $sandbox = false)
1030
- {
1031
- // build url
1032
- $url = '1/fileops/copy';
1033
-
1034
- // build parameters
1035
- $parameters['from_path'] = (string) $fromPath;
1036
- $parameters['to_path'] = (string) $toPath;
1037
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1038
-
1039
- // make the call
1040
- return $this->doCall($url, $parameters, 'POST');
1041
- }
1042
-
1043
-
1044
- /**
1045
- * Create a folder relative to the user's Dropbox root or the user's application sandbox folder.
1046
- *
1047
- * @return array
1048
- * @param string $path The path to the new folder to create, relative to root.
1049
- * @param bool[optional] $sandbox Sandbox mode?
1050
- */
1051
- public function fileopsCreateFolder($path, $sandbox = false)
1052
- {
1053
- // build url
1054
- $url = '1/fileops/create_folder';
1055
-
1056
- // build parameters
1057
- $parameters['path'] = trim((string) $path, '/');
1058
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1059
-
1060
- // make the call
1061
- return $this->doCall($url, $parameters, 'POST');
1062
- }
1063
-
1064
-
1065
- /**
1066
- * Deletes a file or folder.
1067
- *
1068
- * @return array
1069
- * @param string $path path specifies either a file or folder to be deleted. This path is interpreted relative to the location specified by root.
1070
- * @param bool[optional] $sandbox Sandbox mode?
1071
- */
1072
- public function fileopsDelete($path, $sandbox = false)
1073
- {
1074
- // build url
1075
- $url = '1/fileops/delete';
1076
-
1077
- // build parameters
1078
- $parameters['path'] = trim((string) $path, '/');
1079
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1080
- // make the call
1081
- return $this->doCall($url, $parameters, 'POST');
1082
- }
1083
-
1084
-
1085
- /**
1086
- * Move a file or folder to a new location.
1087
- *
1088
- * @return array
1089
- * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1090
- * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1091
- * @param bool[optional] $sandbox Sandbox mode?
1092
- */
1093
- public function fileopsMove($fromPath, $toPath, $sandbox = false)
1094
- {
1095
- // build url
1096
- $url = '1/fileops/move';
1097
-
1098
- // build parameters
1099
- $parameters['from_path'] = (string) $fromPath;
1100
- $parameters['to_path'] = (string) $toPath;
1101
- $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1102
-
1103
- // make the call
1104
- return $this->doCall($url, $parameters, 'POST');
1105
- }
1106
-
1107
- function _log($mixed)
1108
- {
1109
- if (is_array($mixed)) {
1110
- $mixed = print_r($mixed, 1);
1111
- } else if (is_object($mixed)) {
1112
- ob_start();
1113
- var_dump($mixed);
1114
- $mixed = ob_get_clean();
1115
- }
1116
-
1117
- $handle = fopen(dirname(__FILE__) . '/log', 'a');
1118
- fwrite($handle, $mixed . PHP_EOL);
1119
- fclose($handle);
1120
- }
1121
- }
1122
-
1123
-
1124
- /**
1125
- * Dropbox Exception class
1126
- *
1127
- * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
1128
- */
1129
- class DropboxException extends Exception
1130
- {
1131
- }
1132
-
1133
- ?>
1134
-
1
+ <?php
2
+
3
+ /**
4
+ * Dropbox class
5
+ *
6
+ * This source file can be used to communicate with Dropbox (http://dropbox.com)
7
+ *
8
+ * The class is documented in the file itself. If you find any bugs help me out and report them. Reporting can be done by sending an email to php-dropbox-bugs[at]verkoyen[dot]eu.
9
+ * If you report a bug, make sure you give me enough information (include your code).
10
+ *
11
+ * Changelog since 1.0.4
12
+ * - Fixed filesPost so it returns a boolean.
13
+ * - Some code styling
14
+ *
15
+ * Changelog since 1.0.3
16
+ * - Corrected the authorize-URL (thx to Jacob Budin).
17
+ *
18
+ * Changelog since 1.0.2
19
+ * - Added methods to enable oauth-usage.
20
+ *
21
+ * Changelog since 1.0.1
22
+ * - Bugfix: when doing multiple calles where GET and POST is mixed, the postfields should be reset (thx to Daniel Hトてスsken)
23
+ *
24
+ * Changelog since 1.0.0
25
+ * - fixed some issues with generation off the basestring
26
+ *
27
+ * License
28
+ * Copyright (c), Tijs Verkoyen. All rights reserved.
29
+ *
30
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
31
+ *
32
+ * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
33
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
34
+ * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
35
+ *
36
+ * This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
37
+ *
38
+ * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
39
+ * @version 1.0.5
40
+ *
41
+ * @copyright Copyright (c), Tijs Verkoyen. All rights reserved.
42
+ * @license BSD License
43
+ */
44
+ class Dropbox
45
+ {
46
+ // internal constant to enable/disable debugging
47
+ const DEBUG = false;
48
+
49
+ // url for the dropbox-api
50
+ const API_URL = 'https://api.dropbox.com';
51
+ const API_AUTH_URL = 'https://www.dropbox.com';
52
+ const API_CONTENT_URL = 'https://api-content.dropbox.com';
53
+
54
+ // port for the dropbox-api
55
+ const API_PORT = 443;
56
+
57
+ // current version
58
+ const VERSION = '1.0.5';
59
+
60
+
61
+ /**
62
+ * A cURL instance
63
+ *
64
+ * @var resource
65
+ */
66
+ private $curl;
67
+
68
+
69
+ /**
70
+ * The application key
71
+ *
72
+ * @var string
73
+ */
74
+ private $applicationKey;
75
+
76
+
77
+ /**
78
+ * The application secret
79
+ *
80
+ * @var string
81
+ */
82
+ private $applicationSecret;
83
+
84
+
85
+ /**
86
+ * The oAuth-token
87
+ *
88
+ * @var string
89
+ */
90
+ private $oAuthToken = '';
91
+
92
+
93
+ /**
94
+ * The oAuth-token-secret
95
+ *
96
+ * @var string
97
+ */
98
+ private $oAuthTokenSecret = '';
99
+
100
+
101
+ /**
102
+ * The timeout
103
+ *
104
+ * @var int
105
+ */
106
+ private $timeOut = 60;
107
+
108
+
109
+ /**
110
+ * The user agent
111
+ *
112
+ * @var string
113
+ */
114
+ private $userAgent;
115
+
116
+
117
+ // class methods
118
+ /**
119
+ * Default constructor
120
+ *
121
+ * @return void
122
+ * @param string $applicationKey The application key to use.
123
+ * @param string $applicationSecret The application secret to use.
124
+ */
125
+ public function __construct($applicationKey, $applicationSecret)
126
+ {
127
+ $this->setApplicationKey($applicationKey);
128
+ $this->setApplicationSecret($applicationSecret);
129
+ }
130
+
131
+
132
+ /**
133
+ * Default destructor
134
+ *
135
+ * @return void
136
+ */
137
+ public function __destruct()
138
+ {
139
+ if($this->curl != null) curl_close($this->curl);
140
+ }
141
+
142
+
143
+ /**
144
+ * Format the parameters as a querystring
145
+ *
146
+ * @return string
147
+ * @param array $parameters The parameters to pass.
148
+ */
149
+ private function buildQuery(array $parameters)
150
+ {
151
+ // no parameters?
152
+ if(empty($parameters)) return '';
153
+
154
+ // encode the keys
155
+ $keys = self::urlencode_rfc3986(array_keys($parameters));
156
+
157
+ // encode the values
158
+ $values = self::urlencode_rfc3986(array_values($parameters));
159
+
160
+ // reset the parameters
161
+ $parameters = array_combine($keys, $values);
162
+
163
+ // sort parameters by key
164
+ uksort($parameters, 'strcmp');
165
+
166
+ // loop parameters
167
+ foreach($parameters as $key => $value)
168
+ {
169
+ // sort by value
170
+ if(is_array($value)) $parameters[$key] = natsort($value);
171
+ }
172
+
173
+ // process parameters
174
+ foreach($parameters as $key => $value) $chunks[] = $key . '=' . str_replace('%25', '%', $value);
175
+
176
+ // return
177
+ return implode('&', $chunks);
178
+ }
179
+
180
+
181
+ /**
182
+ * All OAuth 1.0 requests use the same basic algorithm for creating a signature base string and a signature.
183
+ * The signature base string is composed of the HTTP method being used, followed by an ampersand ("&") and then the URL-encoded base URL being accessed,
184
+ * complete with path (but not query parameters), followed by an ampersand ("&").
185
+ * Then, you take all query parameters and POST body parameters (when the POST body is of the URL-encoded type, otherwise the POST body is ignored),
186
+ * including the OAuth parameters necessary for negotiation with the request at hand, and sort them in lexicographical order by first parameter name and
187
+ * then parameter value (for duplicate parameters), all the while ensuring that both the key and the value for each parameter are URL encoded in isolation.
188
+ * Instead of using the equals ("=") sign to mark the key/value relationship, you use the URL-encoded form of "%3D". Each parameter is then joined by the
189
+ * URL-escaped ampersand sign, "%26".
190
+ *
191
+ * @return string
192
+ * @param string $url The url to use.
193
+ * @param string $method The method that will be called.
194
+ * @param array $parameters The parameters to pass.
195
+ */
196
+ private function calculateBaseString($url, $method, array $parameters)
197
+ {
198
+ // redefine
199
+ $url = (string) $url;
200
+ $parameters = (array) $parameters;
201
+
202
+ // init var
203
+ $pairs = array();
204
+ $chunks = array();
205
+
206
+ // sort parameters by key
207
+ uksort($parameters, 'strcmp');
208
+
209
+ // loop parameters
210
+ foreach($parameters as $key => $value)
211
+ {
212
+ // sort by value
213
+ if(is_array($value)) $parameters[$key] = natsort($value);
214
+ }
215
+
216
+ // process queries
217
+ foreach($parameters as $key => $value)
218
+ {
219
+ // only add if not already in the url
220
+ if(substr_count($url, $key . '=' . $value) == 0) $chunks[] = self::urlencode_rfc3986($key) . '%3D' . self::urlencode_rfc3986($value);
221
+ }
222
+
223
+ $urlChunks = explode('/', $url);
224
+ $i = 0;
225
+
226
+ foreach($urlChunks as &$chunk)
227
+ {
228
+ if($i > 4) $chunk = self::urlencode_rfc3986($chunk);
229
+ else $chunk = urlencode($chunk);
230
+
231
+ $i++;
232
+
233
+ }
234
+
235
+ // build base
236
+ $base = $method . '&';
237
+ $base .= implode('%2F', $urlChunks);
238
+ $base .= (substr_count($url, '?')) ? '%26' : '&';
239
+ $base .= implode('%26', $chunks);
240
+ $base = str_replace(array('%3F', '%20'), array('&', '%2520'), $base);
241
+
242
+ // return
243
+ return $base;
244
+ }
245
+
246
+
247
+ /**
248
+ * Build the Authorization header
249
+ * @later: fix me
250
+ *
251
+ * @return string
252
+ * @param array $parameters The parameters to pass.
253
+ * @param string $url The url to use.
254
+ */
255
+ private function calculateHeader(array $parameters, $url)
256
+ {
257
+ // redefine
258
+ $url = (string) $url;
259
+
260
+ // divide into parts
261
+ $parts = parse_url($url);
262
+
263
+ // init var
264
+ $chunks = array();
265
+
266
+ // process queries
267
+ foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', self::urlencode_rfc3986($key) . '="' . self::urlencode_rfc3986($value) . '"');
268
+ $parts['path']=str_replace("%2F", "/", rawurlencode($parts['path']));
269
+ // build return
270
+ $return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
271
+ $return .= implode(',', $chunks);
272
+ // prepend name and OAuth part
273
+ return $return;
274
+ }
275
+
276
+
277
+ /**
278
+ * Make an call to the oAuth
279
+ * @todo refactor me
280
+ *
281
+ * @return array
282
+ * @param string $url The url that has to be called.
283
+ * @param array[optional] $parameters The parameters to pass.
284
+ * @param string[optional] $method Which HTTP-method should we use? Possible values are POST, GET.
285
+ * @param bool[optional] $expectJSON Do we expect JSON?
286
+ */
287
+ private function doOAuthCall($url, array $parameters = null, $method = 'POST', $expectJSON = true)
288
+ {
289
+ // redefine
290
+ $url = (string) $url;
291
+
292
+ // append default parameters
293
+ $parameters['oauth_consumer_key'] = $this->getApplicationKey();
294
+ $parameters['oauth_nonce'] = md5(microtime() . rand());
295
+ $parameters['oauth_timestamp'] = time();
296
+ $parameters['oauth_signature_method'] = 'HMAC-SHA1';
297
+ $parameters['oauth_version'] = '1.0';
298
+
299
+ // calculate the base string
300
+ $base = $this->calculateBaseString(self::API_URL . '/' . $url, 'POST', $parameters);
301
+
302
+ // add sign into the parameters
303
+ $parameters['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
304
+
305
+ // calculate header
306
+ $header = $this->calculateHeader($parameters, self::API_URL . '/' . $url);
307
+
308
+ if($method == 'POST')
309
+ {
310
+ $options[CURLOPT_POST] = true;
311
+ $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
312
+ }
313
+
314
+ else
315
+ {
316
+ // reset post
317
+ $options[CURLOPT_POST] = 0;
318
+ unset($options[CURLOPT_POSTFIELDS]);
319
+
320
+ // add the parameters into the querystring
321
+ if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
322
+ }
323
+
324
+ // set options
325
+ $options[CURLOPT_URL] = self::API_URL . '/' . $url;
326
+ $options[CURLOPT_PORT] = self::API_PORT;
327
+ $options[CURLOPT_USERAGENT] = $this->getUserAgent();
328
+ if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
329
+ $options[CURLOPT_RETURNTRANSFER] = true;
330
+ $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
331
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
332
+ $options[CURLOPT_SSL_VERIFYHOST] = false;
333
+ $options[CURLOPT_HTTPHEADER] = array('Expect:');
334
+
335
+ // init
336
+ $this->curl = curl_init();
337
+
338
+ // set options
339
+ curl_setopt_array($this->curl, $options);
340
+
341
+ // execute
342
+ $response = curl_exec($this->curl);
343
+ $headers = curl_getinfo($this->curl);
344
+
345
+ // fetch errors
346
+ $errorNumber = curl_errno($this->curl);
347
+ $errorMessage = curl_error($this->curl);
348
+
349
+ // error?
350
+ if($errorNumber != '') throw new DropboxException($errorMessage, $errorNumber);
351
+
352
+ // return
353
+ if($expectJSON) return json_decode($response, true);
354
+
355
+ // fallback
356
+ return $response;
357
+ }
358
+
359
+
360
+ /**
361
+ * Make the call
362
+ *
363
+ * @return string
364
+ * @param string $url The url to call.
365
+ * @param array[optional] $parameters Optional parameters.
366
+ * @param bool[optional] $method The method to use. Possible values are GET, POST.
367
+ * @param string[optional] $filePath The path to the file to upload.
368
+ * @param bool[optional] $expectJSON Do we expect JSON?
369
+ * @param bool[optional] $isContent Is this content?
370
+ */
371
+ private function doCall($url, array $parameters = null, $method = 'GET', $filePath = null, $expectJSON = true, $isContent = false)
372
+ {
373
+ // allowed methods
374
+ $allowedMethods = array('GET', 'POST');
375
+
376
+ // redefine
377
+ $url = (string) $url;
378
+ $parameters = (array) $parameters;
379
+ $method = (string) $method;
380
+ $expectJSON = (bool) $expectJSON;
381
+
382
+ // validate method
383
+ if(!in_array($method, $allowedMethods)) throw new DropboxException('Unknown method (' . $method . '). Allowed methods are: ' . implode(', ', $allowedMethods));
384
+
385
+ // append default parameters
386
+ $oauth['oauth_consumer_key'] = $this->getApplicationKey();
387
+ $oauth['oauth_nonce'] = md5(microtime() . rand());
388
+ $oauth['oauth_timestamp'] = time();
389
+ $oauth['oauth_token'] = $this->getOAuthToken();
390
+ $oauth['oauth_signature_method'] = 'HMAC-SHA1';
391
+ $oauth['oauth_version'] = '1.0';
392
+
393
+ // set data
394
+ $data = $oauth;
395
+ if(!empty($parameters))
396
+ {
397
+ // convert to UTF-8
398
+ foreach($parameters as &$value) $value = utf8_encode($value);
399
+
400
+ // merge
401
+ $data = array_merge($data, $parameters);
402
+ }
403
+
404
+ if($filePath != null)
405
+ {
406
+ // process file
407
+ $fileInfo = pathinfo($filePath);
408
+
409
+ // add to the data
410
+ $data['file'] = $fileInfo['basename'];
411
+
412
+ }
413
+
414
+ // calculate the base string
415
+ if($isContent) $base = $this->calculateBaseString(self::API_CONTENT_URL . '/' . $url, $method, $data);
416
+ else $base = $this->calculateBaseString(self::API_URL . '/' . $url, $method, $data);
417
+
418
+ // based on the method, we should handle the parameters in a different way
419
+ if($method == 'POST')
420
+ {
421
+ // file provided?
422
+ if($filePath != null)
423
+ {
424
+ // build a boundary
425
+ $boundary = md5(time());
426
+
427
+ // init var
428
+ $content = '--' . $boundary . "\r\n";
429
+
430
+ // set file
431
+ $content .= 'Content-Disposition: form-data; name=file; filename="' . $fileInfo['basename'] . '"' . "\r\n";
432
+ $content .= 'Content-Type: application/octet-stream' . "\r\n";
433
+ $content .= "\r\n";
434
+ $content .= file_get_contents($filePath);
435
+ $content .= "\r\n";
436
+ $content .= "--" . $boundary . '--';
437
+
438
+ // build headers
439
+ $headers[] = 'Content-Type: multipart/form-data; boundary=' . $boundary;
440
+ $headers[] = 'Content-Length: ' . strlen($content);
441
+
442
+ // set content
443
+ $options[CURLOPT_POSTFIELDS] = $content;
444
+ }
445
+
446
+ // no file
447
+ else $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
448
+
449
+ // enable post
450
+ $options[CURLOPT_POST] = 1;
451
+ }
452
+
453
+ else
454
+ {
455
+ // reset post
456
+ $options[CURLOPT_POST] = 0;
457
+ unset($options[CURLOPT_POSTFIELDS]);
458
+ $url=str_replace("%2F", "/", rawurlencode($url));
459
+
460
+ // add the parameters into the querystring
461
+ if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
462
+ }
463
+
464
+ // add sign into the parameters
465
+ $oauth['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
466
+
467
+ if($isContent) $headers[] = $this->calculateHeader($oauth, self::API_CONTENT_URL . '/' . $url);
468
+ else $headers[] = $this->calculateHeader($oauth, self::API_URL . '/' . $url);
469
+ $headers[] = 'Expect:';
470
+
471
+ // set options
472
+ if($isContent) $options[CURLOPT_URL] = self::API_CONTENT_URL . '/' . $url;
473
+ else $options[CURLOPT_URL] = self::API_URL . '/' . $url;
474
+ $options[CURLOPT_PORT] = self::API_PORT;
475
+ $options[CURLOPT_USERAGENT] = $this->getUserAgent();
476
+ if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
477
+ $options[CURLOPT_RETURNTRANSFER] = true;
478
+ $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
479
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
480
+ $options[CURLOPT_SSL_VERIFYHOST] = false;
481
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
482
+ $options[CURLOPT_HTTPHEADER] = $headers;
483
+ // init
484
+ if($this->curl == null) $this->curl = curl_init();
485
+
486
+ // set options
487
+ curl_setopt_array($this->curl, $options);
488
+
489
+ // execute
490
+ $response = curl_exec($this->curl);
491
+ $headers = curl_getinfo($this->curl);
492
+
493
+ // fetch errors
494
+ $errorNumber = curl_errno($this->curl);
495
+ $errorMessage = curl_error($this->curl);
496
+
497
+ if(!$expectJSON && $isContent)
498
+ {
499
+ // is it JSON?
500
+ $json = @json_decode($response, true);
501
+ if($json !== false && isset($json['error'])) throw new DropboxException($json['error']);
502
+
503
+ // set return
504
+ $return['content_type'] = $headers['content_type'];
505
+ $return['data'] = base64_encode($response);
506
+
507
+ // return
508
+ return $return;
509
+ }
510
+
511
+ // we don't expect JSON, return the response
512
+ if(!$expectJSON) return $response;
513
+
514
+ // replace ids with their string values, added because of some PHP-version can't handle these large values
515
+ $response = preg_replace('/id":(\d+)/', 'id":"\1"', $response);
516
+
517
+ // we expect JSON, so decode it
518
+ $json = @json_decode($response, true);
519
+
520
+ // validate JSON
521
+ if($json === null)
522
+ {
523
+ // should we provide debug information
524
+ if(self::DEBUG)
525
+ {
526
+ // make it output proper
527
+ echo '<pre>';
528
+
529
+ // dump the header-information
530
+ var_dump($headers);
531
+
532
+ // dump the error
533
+ var_dump($errorMessage);
534
+
535
+ // dump the raw response
536
+ var_dump($response);
537
+
538
+ // end proper format
539
+ echo '</pre>';
540
+ }
541
+
542
+ // throw exception
543
+ throw new DropboxException('Invalid response.');
544
+ }
545
+
546
+ // any error
547
+ if(isset($json['error']))
548
+ {
549
+ // should we provide debug information
550
+ if(self::DEBUG)
551
+ {
552
+ // make it output proper
553
+ echo '<pre>';
554
+
555
+ // dump the header-information
556
+ var_dump($headers);
557
+
558
+ // dump the raw response
559
+ var_dump($response);
560
+
561
+ // end proper format
562
+ echo '</pre>';
563
+ }
564
+
565
+ if(isset($json['error']) && is_string($json['error'])) $message = $json['error'];
566
+ elseif(isset($json['error']['hash']) && $json['error']['hash'] != '') $message = (string) $json['error']['hash'];
567
+ else $message = 'Invalid response.';
568
+
569
+ // throw exception
570
+ throw new DropboxException($message);
571
+ }
572
+
573
+ // return
574
+ return $json;
575
+ }
576
+
577
+
578
+ /**
579
+ * Get the application key
580
+ *
581
+ * @return string
582
+ */
583
+ private function getApplicationKey()
584
+ {
585
+ return $this->applicationKey;
586
+ }
587
+
588
+
589
+ /**
590
+ * Get the application secret
591
+ *
592
+ * @return string
593
+ */
594
+ private function getApplicationSecret()
595
+ {
596
+ return $this->applicationSecret;
597
+ }
598
+
599
+
600
+ /**
601
+ * Get the oAuth-token
602
+ *
603
+ * @return string
604
+ */
605
+ private function getOAuthToken()
606
+ {
607
+ return $this->oAuthToken;
608
+ }
609
+
610
+
611
+ /**
612
+ * Get the oAuth-token-secret
613
+ *
614
+ * @return string
615
+ */
616
+ private function getOAuthTokenSecret()
617
+ {
618
+ return $this->oAuthTokenSecret;
619
+ }
620
+
621
+
622
+ /**
623
+ * Get the timeout
624
+ *
625
+ * @return int
626
+ */
627
+ public function getTimeOut()
628
+ {
629
+ return (int) $this->timeOut;
630
+ }
631
+
632
+
633
+ /**
634
+ * Get the useragent that will be used. Our version will be prepended to yours.
635
+ * It will look like: "PHP Dropbox/<version> <your-user-agent>"
636
+ *
637
+ * @return string
638
+ */
639
+ public function getUserAgent()
640
+ {
641
+ return (string) 'PHP Dropbox/' . self::VERSION . ' ' . $this->userAgent;
642
+ }
643
+
644
+
645
+ /**
646
+ * Set the application key
647
+ *
648
+ * @return void
649
+ * @param string $key The application key to use.
650
+ */
651
+ private function setApplicationKey($key)
652
+ {
653
+ $this->applicationKey = (string) $key;
654
+ }
655
+
656
+
657
+ /**
658
+ * Set the application secret
659
+ *
660
+ * @return void
661
+ * @param string $secret The application secret to use.
662
+ */
663
+ private function setApplicationSecret($secret)
664
+ {
665
+ $this->applicationSecret = (string) $secret;
666
+ }
667
+
668
+
669
+ /**
670
+ * Set the oAuth-token
671
+ *
672
+ * @return void
673
+ * @param string $token The token to use.
674
+ */
675
+ public function setOAuthToken($token)
676
+ {
677
+ $this->oAuthToken = (string) $token;
678
+ }
679
+
680
+
681
+ /**
682
+ * Set the oAuth-secret
683
+ *
684
+ * @return void
685
+ * @param string $secret The secret to use.
686
+ */
687
+ public function setOAuthTokenSecret($secret)
688
+ {
689
+ $this->oAuthTokenSecret = (string) $secret;
690
+ }
691
+
692
+
693
+ /**
694
+ * Set the timeout
695
+ *
696
+ * @return void
697
+ * @param int $seconds The timeout in seconds.
698
+ */
699
+ public function setTimeOut($seconds)
700
+ {
701
+ $this->timeOut = (int) $seconds;
702
+ }
703
+
704
+
705
+ /**
706
+ * Get the useragent that will be used. Our version will be prepended to yours.
707
+ * It will look like: "PHP Dropbox/<version> <your-user-agent>"
708
+ *
709
+ * @return void
710
+ * @param string $userAgent Your user-agent, it should look like <app-name>/<app-version>.
711
+ */
712
+ public function setUserAgent($userAgent)
713
+ {
714
+ $this->userAgent = (string) $userAgent;
715
+ }
716
+
717
+
718
+ /**
719
+ * Build the signature for the data
720
+ *
721
+ * @return string
722
+ * @param string $key The key to use for signing.
723
+ * @param string $data The data that has to be signed.
724
+ */
725
+ private function hmacsha1($key, $data)
726
+ {
727
+ return base64_encode(hash_hmac('SHA1', $data, $key, true));
728
+ }
729
+
730
+
731
+ /**
732
+ * URL-encode method for internatl use
733
+ *
734
+ * @return string
735
+ * @param mixed $value The value to encode.
736
+ */
737
+ private static function urlencode_rfc3986($value)
738
+ {
739
+ if(is_array($value)) return array_map(array('Dropbox', 'urlencode_rfc3986'), $value);
740
+ else
741
+ {
742
+ $search = array('+', ' ', '%7E', '%');
743
+ $replace = array('%20', '%20', '~', '%25');
744
+
745
+ return str_replace($search, $replace, rawurlencode($value));
746
+ }
747
+ }
748
+
749
+
750
+ // oauth resources
751
+ /**
752
+ * Call for obtaining an OAuth request token.
753
+ * Returns a request token and the corresponding request token secret. This token and secret cannot be used to sign requests for the /metadata and /file content API calls.
754
+ * Their only purpose is for signing a request to oauth/access_token once the user has gone through the application authorization steps provided by oauth/authorize.
755
+ *
756
+ * @return array
757
+ */
758
+ public function oAuthRequestToken()
759
+ {
760
+ // make the call
761
+ $response = $this->doOAuthCall('1/oauth/request_token', null, 'POST', false);
762
+
763
+ // process response
764
+ $response = (array) explode('&', $response);
765
+ $return = array();
766
+
767
+ // loop chunks
768
+ foreach($response as $chunk)
769
+ {
770
+ // split again
771
+ $chunks = explode('=', $chunk, 2);
772
+
773
+ // store return
774
+ if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
775
+ }
776
+
777
+ // return
778
+ return $return;
779
+ }
780
+
781
+
782
+ /**
783
+ * Redirect the user to the oauth/authorize location so that Dropbox can authenticate the user and ask whether or not the user wants to authorize the application to access
784
+ * file metadata and content on its behalf. oauth/authorize is not an API call per se, because it does not have a return value, but rather directs the user to a page on
785
+ * api.dropbox.com where they are provided means to log in to Dropbox and grant authority to the application requesting it.
786
+ * The page served by oauth/authorize should be presented to the user through their web browser.
787
+ * Please note, without directing the user to a Dropbox-provided page via oauth/authorize, it is impossible for your application to use the request token it received
788
+ * via oauth/request_token to obtain an access token from oauth/access_token.
789
+ *
790
+ * @return void
791
+ * @param string $oauthToken The request token of the application requesting authority from a user.
792
+ * @param string[optional] $oauthCallback After the user authorizes an application, the user is redirected to the application-served URL provided by this parameter.
793
+ */
794
+ public function oAuthAuthorize($oauthToken, $oauthCallback = null)
795
+ {
796
+ // build parameters
797
+ $parameters = array();
798
+ $parameters['oauth_token'] = (string) $oauthToken;
799
+ if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
800
+
801
+ // build url
802
+ $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
803
+
804
+ // redirect
805
+ header('Location: ' . $url);
806
+ exit;
807
+ }
808
+
809
+ public function mwp_oAuthAuthorize($oauthToken, $oauthCallback = null)
810
+ {
811
+ // build parameters
812
+ $parameters = array();
813
+ $parameters['oauth_token'] = (string) $oauthToken;
814
+ if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
815
+
816
+ // build url
817
+ $url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
818
+
819
+ return $url;
820
+ }
821
+
822
+ /**
823
+ * This call returns a access token and the corresponding access token secret.
824
+ * Upon return, the authorization process is now complete and the access token and corresponding secret are used to sign requests for the metadata and file content API calls.
825
+ *
826
+ * @return array
827
+ * @param string $oauthToken The token returned after authorizing.
828
+ */
829
+ public function oAuthAccessToken($oauthToken)
830
+ {
831
+ // build parameters
832
+ $parameters = array();
833
+ $parameters['oauth_token'] = (string) $oauthToken;
834
+
835
+ // make the call
836
+ $response = $this->doOAuthCall('1/oauth/access_token', $parameters, 'POST', false);
837
+
838
+ // process response
839
+ $response = (array) explode('&', $response);
840
+ $return = array();
841
+
842
+ // loop chunks
843
+ foreach($response as $chunk)
844
+ {
845
+ // split again
846
+ $chunks = explode('=', $chunk, 2);
847
+
848
+ // store return
849
+ if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
850
+ }
851
+
852
+ // return
853
+ return $return;
854
+ }
855
+
856
+
857
+ // token resources
858
+ /**
859
+ * The token call provides a consumer/secret key pair you can use to consistently access the user's account.
860
+ * This is the preferred method of authentication over storing the username and password.
861
+ * Use the key pair as a signature with every subsequent call.
862
+ * The request must be signed using the application's developer and secret key token. Request or access tokens are necessary.
863
+ *
864
+ * Warning: DO NOT STORE THE USER'S PASSWORD! The way this call works is you call it once with the user's email and password and then
865
+ * keep the token around for later. You do NOT (I repeat NOT) call this before everything you do or on each program startup.
866
+ * We watch for this and will shut down your application with little notice if we catch you.
867
+ * In fact, the Objective-C code does this for you so you can't get it wrong.
868
+ *
869
+ * @return array Upon successful verification of the user's credentials, returns an array representation of the access token and secret.
870
+ * @param string $email The email account of the user.
871
+ * @param string $password The password of the user.
872
+ */
873
+ public function token($email, $password)
874
+ {
875
+ // build parameters
876
+ $parameters = array();
877
+ $parameters['email'] = (string) $email;
878
+ $parameters['password'] = (string) $password;
879
+
880
+ // make the call
881
+ $response = (array) $this->doOAuthCall('1/token', $parameters);
882
+
883
+ // validate and set
884
+ if(isset($response['token'])) $this->setOAuthToken($response['token']);
885
+ if(isset($response['secret'])) $this->setOAuthTokenSecret($response['secret']);
886
+
887
+ // return
888
+ return $response;
889
+ }
890
+
891
+
892
+ // account resources
893
+ /**
894
+ * Given a set of account information, the account call allows an application to create a new Dropbox user account.
895
+ * This is useful for situations where the trusted third party application is possibly the user's first interaction with Dropbox.
896
+ *
897
+ * @return bool
898
+ * @param string $email The email account of the user.
899
+ * @param string $password The password for the user.
900
+ * @param string $firstName The user's first name.
901
+ * @param string $lastName The user's last name.
902
+ */
903
+ public function account($email, $password, $firstName, $lastName)
904
+ {
905
+ // build parameters
906
+ $parameters['email'] = (string) $email;
907
+ $parameters['first_name'] = (string) $firstName;
908
+ $parameters['last_name'] = (string) $lastName;
909
+ $parameters['password'] = (string) $password;
910
+
911
+ return (bool) ($this->doCall('1/account', $parameters, 'POST', null, false) == 'OK');
912
+ }
913
+
914
+
915
+ /**
916
+ * Get the user account information.
917
+ *
918
+ * @return array
919
+ */
920
+ public function accountInfo()
921
+ {
922
+ // make the call
923
+ return (array) $this->doCall('1/account/info');
924
+ }
925
+
926
+
927
+ // files & metadata
928
+ /**
929
+ * Retrieves file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
930
+ *
931
+ * @return string
932
+ * @param string $path Path of the directory wherin the file is located.
933
+ * @param bool[optional] $sandbox Sandbox mode?
934
+ */
935
+ public function filesGet($path, $sandbox = false)
936
+ {
937
+ // build url
938
+ $url = '1/files/';
939
+ $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
940
+ $url .= trim((string) $path, '/');
941
+
942
+ // make the call
943
+ return $this->doCall($url, null, 'GET', null, false, true);
944
+ }
945
+
946
+
947
+ /**
948
+ * Uploads file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
949
+ *
950
+ * @return bool
951
+ * @param string $path Path of the directory wherin the file should be uploaded.
952
+ * @param string $localFile Path to the local file.
953
+ * @param bool[optional] $sandbox Sandbox mode?
954
+ */
955
+ public function filesPost($path, $localFile, $sandbox = false)
956
+ {
957
+ // build url
958
+ $url = '1/files/';
959
+ $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
960
+ $url .= trim((string) $path, '/');
961
+
962
+ // make the call
963
+ $return = $this->doCall($url, null, 'POST', $localFile, true, true);
964
+ // return the result
965
+ return (bool) (isset($return['size']) && $return['size'] == 'winner!');
966
+ }
967
+
968
+
969
+ /**
970
+ * Returns metadata for the file or directory at the given <path> location relative to the user's Dropbox or
971
+ * the user's application sandbox. If <path> represents a directory and the list parameter is true, the metadata will
972
+ * also include a listing of metadata for the directory's contents.
973
+ *
974
+ * @return array
975
+ * @param string[optional] $path The path to the file/director to get the metadata for.
976
+ * @param int[optional] $fileLimit When listing a directory, the service will not report listings containing more than $fileLimit files.
977
+ * @param bool[optional] $hash Listing return values include a hash representing the state of the directory's contents.
978
+ * @param bool[optional] $list If true, this call returns a list of metadata representations for the contents of the directory. If false, this call returns the metadata for the directory itself.
979
+ * @param bool[optional] $sandbox Sandbox mode?
980
+ */
981
+ public function metadata($path = '', $fileLimit = 10000, $hash = false, $list = true, $sandbox = false)
982
+ {
983
+ // build url
984
+ $url = '1/metadata/';
985
+ $url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
986
+ $url .= trim((string) $path, '/');
987
+
988
+ // build parameters
989
+ $parameters = null;
990
+ $parameters['file_limit'] = (int) $fileLimit;
991
+ if((bool) $hash) $parameters['hash'] = '';
992
+ $parameters['list'] = ($list) ? 'true': 'false';
993
+
994
+ // make the call
995
+ return (array) $this->doCall($url, $parameters);
996
+ }
997
+
998
+
999
+ /**
1000
+ * Get a minimized thumbnail for a photo.
1001
+ *
1002
+ * @return string Will return a base64_encode string with the JPEG-data
1003
+ * @param string $path The path to the photo.
1004
+ * @param string[optional] $size The size, possible values are: 'small' (32x32), 'medium' (64x64), 'large' (128x128).
1005
+ */
1006
+ public function thumbnails($path, $size = 'small')
1007
+ {
1008
+ // build url
1009
+ $url = '1/thumbnails/dropbox/';
1010
+ $url .= trim((string) $path, '/');
1011
+
1012
+ // build parameters
1013
+ $parameters['size'] = (string) $size;
1014
+
1015
+ // make the call
1016
+ return $this->doCall($url, $parameters, 'GET', null, false, true);
1017
+ }
1018
+
1019
+
1020
+ // file operations
1021
+ /**
1022
+ * Copy a file or folder to a new location.
1023
+ *
1024
+ * @return array
1025
+ * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1026
+ * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1027
+ * @param bool[optional] $sandbox Sandbox mode?
1028
+ */
1029
+ public function fileopsCopy($fromPath, $toPath, $sandbox = false)
1030
+ {
1031
+ // build url
1032
+ $url = '1/fileops/copy';
1033
+
1034
+ // build parameters
1035
+ $parameters['from_path'] = (string) $fromPath;
1036
+ $parameters['to_path'] = (string) $toPath;
1037
+ $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1038
+
1039
+ // make the call
1040
+ return $this->doCall($url, $parameters, 'POST');
1041
+ }
1042
+
1043
+
1044
+ /**
1045
+ * Create a folder relative to the user's Dropbox root or the user's application sandbox folder.
1046
+ *
1047
+ * @return array
1048
+ * @param string $path The path to the new folder to create, relative to root.
1049
+ * @param bool[optional] $sandbox Sandbox mode?
1050
+ */
1051
+ public function fileopsCreateFolder($path, $sandbox = false)
1052
+ {
1053
+ // build url
1054
+ $url = '1/fileops/create_folder';
1055
+
1056
+ // build parameters
1057
+ $parameters['path'] = trim((string) $path, '/');
1058
+ $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1059
+
1060
+ // make the call
1061
+ return $this->doCall($url, $parameters, 'POST');
1062
+ }
1063
+
1064
+
1065
+ /**
1066
+ * Deletes a file or folder.
1067
+ *
1068
+ * @return array
1069
+ * @param string $path path specifies either a file or folder to be deleted. This path is interpreted relative to the location specified by root.
1070
+ * @param bool[optional] $sandbox Sandbox mode?
1071
+ */
1072
+ public function fileopsDelete($path, $sandbox = false)
1073
+ {
1074
+ // build url
1075
+ $url = '1/fileops/delete';
1076
+
1077
+ // build parameters
1078
+ $parameters['path'] = trim((string) $path, '/');
1079
+ $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1080
+ // make the call
1081
+ return $this->doCall($url, $parameters, 'POST');
1082
+ }
1083
+
1084
+
1085
+ /**
1086
+ * Move a file or folder to a new location.
1087
+ *
1088
+ * @return array
1089
+ * @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
1090
+ * @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
1091
+ * @param bool[optional] $sandbox Sandbox mode?
1092
+ */
1093
+ public function fileopsMove($fromPath, $toPath, $sandbox = false)
1094
+ {
1095
+ // build url
1096
+ $url = '1/fileops/move';
1097
+
1098
+ // build parameters
1099
+ $parameters['from_path'] = (string) $fromPath;
1100
+ $parameters['to_path'] = (string) $toPath;
1101
+ $parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
1102
+
1103
+ // make the call
1104
+ return $this->doCall($url, $parameters, 'POST');
1105
+ }
1106
+
1107
+ function _log($mixed)
1108
+ {
1109
+ if (is_array($mixed)) {
1110
+ $mixed = print_r($mixed, 1);
1111
+ } else if (is_object($mixed)) {
1112
+ ob_start();
1113
+ var_dump($mixed);
1114
+ $mixed = ob_get_clean();
1115
+ }
1116
+
1117
+ $handle = fopen(dirname(__FILE__) . '/log', 'a');
1118
+ fwrite($handle, $mixed . PHP_EOL);
1119
+ fclose($handle);
1120
+ }
1121
+ }
1122
+
1123
+
1124
+ /**
1125
+ * Dropbox Exception class
1126
+ *
1127
+ * @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
1128
+ */
1129
+ class DropboxException extends Exception
1130
+ {
1131
+ }
1132
+
1133
+ ?>
1134
+
lib/dropbox.php CHANGED
@@ -1,144 +1,144 @@
1
- <?php
2
- /**
3
- * Dropbox Uploader
4
- *
5
- * Copyright (c) 2009 Jaka Jancar
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * @author Jaka Jancar [jaka@kubje.org] [http://jaka.kubje.org/]
26
- * @version 1.1.5
27
- */
28
- class DropboxUploader {
29
- protected $email;
30
- protected $password;
31
- protected $caCertSourceType = self::CACERT_SOURCE_SYSTEM;
32
- const CACERT_SOURCE_SYSTEM = 0;
33
- const CACERT_SOURCE_FILE = 1;
34
- const CACERT_SOURCE_DIR = 2;
35
- protected $caCertSource;
36
- protected $loggedIn = false;
37
- protected $cookies = array();
38
-
39
- /**
40
- * Constructor
41
- *
42
- * @param string $email
43
- * @param string|null $password
44
- */
45
- public function __construct($email, $password) {
46
- // Check requirements
47
- if (!extension_loaded('curl'))
48
- throw new Exception('DropboxUploader requires the cURL extension.');
49
-
50
- $this->email = $email;
51
- $this->password = $password;
52
- }
53
-
54
- public function setCaCertificateFile($file)
55
- {
56
- $this->caCertSourceType = self::CACERT_SOURCE_FILE;
57
- $this->caCertSource = $file;
58
- }
59
-
60
- public function setCaCertificateDir($dir)
61
- {
62
- $this->caCertSourceType = self::CACERT_SOURCE_DIR;
63
- $this->caCertSource = $dir;
64
- }
65
-
66
- public function upload($filename, $remoteDir='/') {
67
- if (!file_exists($filename) or !is_file($filename) or !is_readable($filename))
68
- throw new Exception("File '$filename' does not exist or is not readable.");
69
-
70
- if (!is_string($remoteDir))
71
- throw new Exception("Remote directory must be a string, is ".gettype($remoteDir)." instead.");
72
-
73
- if (!$this->loggedIn)
74
- $this->login();
75
-
76
- $data = $this->request('https://www.dropbox.com/home');
77
- $token = $this->extractToken($data, 'https://dl-web.dropbox.com/upload');
78
-
79
- $data = $this->request('https://dl-web.dropbox.com/upload', true, array('plain'=>'yes', 'file'=>'@'.$filename, 'dest'=>$remoteDir, 't'=>$token));
80
- if (strpos($data, 'HTTP/1.1 302 FOUND') === false)
81
- throw new Exception('Upload failed!');
82
- }
83
-
84
- protected function login() {
85
- $data = $this->request('https://www.dropbox.com/login');
86
- $token = $this->extractToken($data, '/login');
87
-
88
- $data = $this->request('https://www.dropbox.com/login', true, array('login_email'=>$this->email, 'login_password'=>$this->password, 't'=>$token));
89
-
90
- if (stripos($data, 'location: /home') === false)
91
- throw new Exception('Login unsuccessful.');
92
-
93
- $this->loggedIn = true;
94
- }
95
-
96
- protected function request($url, $post=false, $postData=array()) {
97
- $ch = curl_init();
98
- curl_setopt($ch, CURLOPT_URL, $url);
99
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
100
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
101
- switch ($this->caCertSourceType) {
102
- case self::CACERT_SOURCE_FILE:
103
- curl_setopt($ch, CURLOPT_CAINFO, $this->caCertSource);
104
- break;
105
- case self::CACERT_SOURCE_DIR:
106
- curl_setopt($ch, CURLOPT_CAPATH, $this->caCertSource);
107
- break;
108
- }
109
- curl_setopt($ch, CURLOPT_HEADER, 1);
110
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
111
- if ($post) {
112
- curl_setopt($ch, CURLOPT_POST, $post);
113
- curl_setopt($ch, CURLOPT_POSTFIELDS, array_map('stripcslashes', $postData));
114
- }
115
-
116
- // Send cookies
117
- $rawCookies = array();
118
- foreach ($this->cookies as $k=>$v)
119
- $rawCookies[] = "$k=$v";
120
- $rawCookies = implode(';', $rawCookies);
121
- curl_setopt($ch, CURLOPT_COOKIE, $rawCookies);
122
-
123
- $data = curl_exec($ch);
124
-
125
- if ($data === false)
126
- throw new Exception('Cannot execute request: '.curl_error($ch));
127
-
128
- // Store received cookies
129
- preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER);
130
- foreach ($matches as $match)
131
- $this->cookies[$match[1]] = $match[2];
132
-
133
- curl_close($ch);
134
-
135
- return $data;
136
- }
137
-
138
- protected function extractToken($html, $formAction) {
139
- if (!preg_match('/<form [^>]*'.preg_quote($formAction, '/').'[^>]*>.*?(<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is', $html, $matches) || !isset($matches[2]))
140
- throw new Exception("Cannot extract token! (form action=$formAction)");
141
- return $matches[2];
142
- }
143
-
144
- }
1
+ <?php
2
+ /**
3
+ * Dropbox Uploader
4
+ *
5
+ * Copyright (c) 2009 Jaka Jancar
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ *
25
+ * @author Jaka Jancar [jaka@kubje.org] [http://jaka.kubje.org/]
26
+ * @version 1.1.5
27
+ */
28
+ class DropboxUploader {
29
+ protected $email;
30
+ protected $password;
31
+ protected $caCertSourceType = self::CACERT_SOURCE_SYSTEM;
32
+ const CACERT_SOURCE_SYSTEM = 0;
33
+ const CACERT_SOURCE_FILE = 1;
34
+ const CACERT_SOURCE_DIR = 2;
35
+ protected $caCertSource;
36
+ protected $loggedIn = false;
37
+ protected $cookies = array();
38
+
39
+ /**
40
+ * Constructor
41
+ *
42
+ * @param string $email
43
+ * @param string|null $password
44
+ */
45
+ public function __construct($email, $password) {
46
+ // Check requirements
47
+ if (!extension_loaded('curl'))
48
+ throw new Exception('DropboxUploader requires the cURL extension.');
49
+
50
+ $this->email = $email;
51
+ $this->password = $password;
52
+ }
53
+
54
+ public function setCaCertificateFile($file)
55
+ {
56
+ $this->caCertSourceType = self::CACERT_SOURCE_FILE;
57
+ $this->caCertSource = $file;
58
+ }
59
+
60
+ public function setCaCertificateDir($dir)
61
+ {
62
+ $this->caCertSourceType = self::CACERT_SOURCE_DIR;
63
+ $this->caCertSource = $dir;
64
+ }
65
+
66
+ public function upload($filename, $remoteDir='/') {
67
+ if (!file_exists($filename) or !is_file($filename) or !is_readable($filename))
68
+ throw new Exception("File '$filename' does not exist or is not readable.");
69
+
70
+ if (!is_string($remoteDir))
71
+ throw new Exception("Remote directory must be a string, is ".gettype($remoteDir)." instead.");
72
+
73
+ if (!$this->loggedIn)
74
+ $this->login();
75
+
76
+ $data = $this->request('https://www.dropbox.com/home');
77
+ $token = $this->extractToken($data, 'https://dl-web.dropbox.com/upload');
78
+
79
+ $data = $this->request('https://dl-web.dropbox.com/upload', true, array('plain'=>'yes', 'file'=>'@'.$filename, 'dest'=>$remoteDir, 't'=>$token));
80
+ if (strpos($data, 'HTTP/1.1 302 FOUND') === false)
81
+ throw new Exception('Upload failed!');
82
+ }
83
+
84
+ protected function login() {
85
+ $data = $this->request('https://www.dropbox.com/login');
86
+ $token = $this->extractToken($data, '/login');
87
+
88
+ $data = $this->request('https://www.dropbox.com/login', true, array('login_email'=>$this->email, 'login_password'=>$this->password, 't'=>$token));
89
+
90
+ if (stripos($data, 'location: /home') === false)
91
+ throw new Exception('Login unsuccessful.');
92
+
93
+ $this->loggedIn = true;
94
+ }
95
+
96
+ protected function request($url, $post=false, $postData=array()) {
97
+ $ch = curl_init();
98
+ curl_setopt($ch, CURLOPT_URL, $url);
99
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
100
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
101
+ switch ($this->caCertSourceType) {
102
+ case self::CACERT_SOURCE_FILE:
103
+ curl_setopt($ch, CURLOPT_CAINFO, $this->caCertSource);
104
+ break;
105
+ case self::CACERT_SOURCE_DIR:
106
+ curl_setopt($ch, CURLOPT_CAPATH, $this->caCertSource);
107
+ break;
108
+ }
109
+ curl_setopt($ch, CURLOPT_HEADER, 1);
110
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
111
+ if ($post) {
112
+ curl_setopt($ch, CURLOPT_POST, $post);
113
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array_map('stripcslashes', $postData));
114
+ }
115
+
116
+ // Send cookies
117
+ $rawCookies = array();
118
+ foreach ($this->cookies as $k=>$v)
119
+ $rawCookies[] = "$k=$v";
120
+ $rawCookies = implode(';', $rawCookies);
121
+ curl_setopt($ch, CURLOPT_COOKIE, $rawCookies);
122
+
123
+ $data = curl_exec($ch);
124
+
125
+ if ($data === false)
126
+ throw new Exception('Cannot execute request: '.curl_error($ch));
127
+
128
+ // Store received cookies
129
+ preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER);
130
+ foreach ($matches as $match)
131
+ $this->cookies[$match[1]] = $match[2];
132
+
133
+ curl_close($ch);
134
+
135
+ return $data;
136
+ }
137
+
138
+ protected function extractToken($html, $formAction) {
139
+ if (!preg_match('/<form [^>]*'.preg_quote($formAction, '/').'[^>]*>.*?(<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is', $html, $matches) || !isset($matches[2]))
140
+ throw new Exception("Cannot extract token! (form action=$formAction)");
141
+ return $matches[2];
142
+ }
143
+
144
+ }
lib/json/JSON.php CHANGED
@@ -1,806 +1,806 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Converts to and from JSON format.
6
- *
7
- * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
- * format. It is easy for humans to read and write. It is easy for machines
9
- * to parse and generate. It is based on a subset of the JavaScript
10
- * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
- * This feature can also be found in Python. JSON is a text format that is
12
- * completely language independent but uses conventions that are familiar
13
- * to programmers of the C-family of languages, including C, C++, C#, Java,
14
- * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
- * ideal data-interchange language.
16
- *
17
- * This package provides a simple encoder and decoder for JSON notation. It
18
- * is intended for use with client-side Javascript applications that make
19
- * use of HTTPRequest to perform server communication functions - data can
20
- * be encoded into JSON notation for use in a client-side javascript, or
21
- * decoded from incoming Javascript requests. JSON format is native to
22
- * Javascript, and can be directly eval()'ed with no further parsing
23
- * overhead
24
- *
25
- * All strings should be in ASCII or UTF-8 format!
26
- *
27
- * LICENSE: Redistribution and use in source and binary forms, with or
28
- * without modification, are permitted provided that the following
29
- * conditions are met: Redistributions of source code must retain the
30
- * above copyright notice, this list of conditions and the following
31
- * disclaimer. Redistributions in binary form must reproduce the above
32
- * copyright notice, this list of conditions and the following disclaimer
33
- * in the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
- * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
- * DAMAGE.
47
- *
48
- * @category
49
- * @package Services_JSON
50
- * @author Michal Migurski <mike-json@teczno.com>
51
- * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
- * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
- * @copyright 2005 Michal Migurski
54
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
- * @license http://www.opensource.org/licenses/bsd-license.php
56
- * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
- */
58
-
59
- /**
60
- * Marker constant for Services_JSON::decode(), used to flag stack state
61
- */
62
- define('SERVICES_JSON_SLICE', 1);
63
-
64
- /**
65
- * Marker constant for Services_JSON::decode(), used to flag stack state
66
- */
67
- define('SERVICES_JSON_IN_STR', 2);
68
-
69
- /**
70
- * Marker constant for Services_JSON::decode(), used to flag stack state
71
- */
72
- define('SERVICES_JSON_IN_ARR', 3);
73
-
74
- /**
75
- * Marker constant for Services_JSON::decode(), used to flag stack state
76
- */
77
- define('SERVICES_JSON_IN_OBJ', 4);
78
-
79
- /**
80
- * Marker constant for Services_JSON::decode(), used to flag stack state
81
- */
82
- define('SERVICES_JSON_IN_CMT', 5);
83
-
84
- /**
85
- * Behavior switch for Services_JSON::decode()
86
- */
87
- define('SERVICES_JSON_LOOSE_TYPE', 16);
88
-
89
- /**
90
- * Behavior switch for Services_JSON::decode()
91
- */
92
- define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
-
94
- /**
95
- * Converts to and from JSON format.
96
- *
97
- * Brief example of use:
98
- *
99
- * <code>
100
- * // create a new instance of Services_JSON
101
- * $json = new Services_JSON();
102
- *
103
- * // convert a complexe value to JSON notation, and send it to the browser
104
- * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
- * $output = $json->encode($value);
106
- *
107
- * print($output);
108
- * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
- *
110
- * // accept incoming POST data, assumed to be in JSON notation
111
- * $input = file_get_contents('php://input', 1000000);
112
- * $value = $json->decode($input);
113
- * </code>
114
- */
115
- class Services_JSON
116
- {
117
- /**
118
- * constructs a new JSON instance
119
- *
120
- * @param int $use object behavior flags; combine with boolean-OR
121
- *
122
- * possible values:
123
- * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
- * "{...}" syntax creates associative arrays
125
- * instead of objects in decode().
126
- * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
- * Values which can't be encoded (e.g. resources)
128
- * appear as NULL instead of throwing errors.
129
- * By default, a deeply-nested resource will
130
- * bubble up with an error, so all return values
131
- * from encode() should be checked with isError()
132
- */
133
- function Services_JSON($use = 0)
134
- {
135
- $this->use = $use;
136
- }
137
-
138
- /**
139
- * convert a string from one UTF-16 char to one UTF-8 char
140
- *
141
- * Normally should be handled by mb_convert_encoding, but
142
- * provides a slower PHP-only method for installations
143
- * that lack the multibye string extension.
144
- *
145
- * @param string $utf16 UTF-16 character
146
- * @return string UTF-8 character
147
- * @access private
148
- */
149
- function utf162utf8($utf16)
150
- {
151
- // oh please oh please oh please oh please oh please
152
- if(function_exists('mb_convert_encoding')) {
153
- return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
- }
155
-
156
- $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
157
-
158
- switch(true) {
159
- case ((0x7F & $bytes) == $bytes):
160
- // this case should never be reached, because we are in ASCII range
161
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
- return chr(0x7F & $bytes);
163
-
164
- case (0x07FF & $bytes) == $bytes:
165
- // return a 2-byte UTF-8 character
166
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
- return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
- . chr(0x80 | ($bytes & 0x3F));
169
-
170
- case (0xFFFF & $bytes) == $bytes:
171
- // return a 3-byte UTF-8 character
172
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
- return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
- . chr(0x80 | (($bytes >> 6) & 0x3F))
175
- . chr(0x80 | ($bytes & 0x3F));
176
- }
177
-
178
- // ignoring UTF-32 for now, sorry
179
- return '';
180
- }
181
-
182
- /**
183
- * convert a string from one UTF-8 char to one UTF-16 char
184
- *
185
- * Normally should be handled by mb_convert_encoding, but
186
- * provides a slower PHP-only method for installations
187
- * that lack the multibye string extension.
188
- *
189
- * @param string $utf8 UTF-8 character
190
- * @return string UTF-16 character
191
- * @access private
192
- */
193
- function utf82utf16($utf8)
194
- {
195
- // oh please oh please oh please oh please oh please
196
- if(function_exists('mb_convert_encoding')) {
197
- return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
- }
199
-
200
- switch(strlen($utf8)) {
201
- case 1:
202
- // this case should never be reached, because we are in ASCII range
203
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
- return $utf8;
205
-
206
- case 2:
207
- // return a UTF-16 character from a 2-byte UTF-8 char
208
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
- return chr(0x07 & (ord($utf8{0}) >> 2))
210
- . chr((0xC0 & (ord($utf8{0}) << 6))
211
- | (0x3F & ord($utf8{1})));
212
-
213
- case 3:
214
- // return a UTF-16 character from a 3-byte UTF-8 char
215
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
- return chr((0xF0 & (ord($utf8{0}) << 4))
217
- | (0x0F & (ord($utf8{1}) >> 2)))
218
- . chr((0xC0 & (ord($utf8{1}) << 6))
219
- | (0x7F & ord($utf8{2})));
220
- }
221
-
222
- // ignoring UTF-32 for now, sorry
223
- return '';
224
- }
225
-
226
- /**
227
- * encodes an arbitrary variable into JSON format
228
- *
229
- * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
- * see argument 1 to Services_JSON() above for array-parsing behavior.
231
- * if var is a strng, note that encode() always expects it
232
- * to be in ASCII or UTF-8 format!
233
- *
234
- * @return mixed JSON string representation of input var or an error if a problem occurs
235
- * @access public
236
- */
237
- function encode($var)
238
- {
239
- switch (gettype($var)) {
240
- case 'boolean':
241
- return $var ? 'true' : 'false';
242
-
243
- case 'NULL':
244
- return 'null';
245
-
246
- case 'integer':
247
- return (int) $var;
248
-
249
- case 'double':
250
- case 'float':
251
- return (float) $var;
252
-
253
- case 'string':
254
- // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
255
- $ascii = '';
256
- $strlen_var = strlen($var);
257
-
258
- /*
259
- * Iterate over every character in the string,
260
- * escaping with a slash or encoding to UTF-8 where necessary
261
- */
262
- for ($c = 0; $c < $strlen_var; ++$c) {
263
-
264
- $ord_var_c = ord($var{$c});
265
-
266
- switch (true) {
267
- case $ord_var_c == 0x08:
268
- $ascii .= '\b';
269
- break;
270
- case $ord_var_c == 0x09:
271
- $ascii .= '\t';
272
- break;
273
- case $ord_var_c == 0x0A:
274
- $ascii .= '\n';
275
- break;
276
- case $ord_var_c == 0x0C:
277
- $ascii .= '\f';
278
- break;
279
- case $ord_var_c == 0x0D:
280
- $ascii .= '\r';
281
- break;
282
-
283
- case $ord_var_c == 0x22:
284
- case $ord_var_c == 0x2F:
285
- case $ord_var_c == 0x5C:
286
- // double quote, slash, slosh
287
- $ascii .= '\\'.$var{$c};
288
- break;
289
-
290
- case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
291
- // characters U-00000000 - U-0000007F (same as ASCII)
292
- $ascii .= $var{$c};
293
- break;
294
-
295
- case (($ord_var_c & 0xE0) == 0xC0):
296
- // characters U-00000080 - U-000007FF, mask 110XXXXX
297
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
298
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
299
- $c += 1;
300
- $utf16 = $this->utf82utf16($char);
301
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
302
- break;
303
-
304
- case (($ord_var_c & 0xF0) == 0xE0):
305
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
306
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
307
- $char = pack('C*', $ord_var_c,
308
- ord($var{$c + 1}),
309
- ord($var{$c + 2}));
310
- $c += 2;
311
- $utf16 = $this->utf82utf16($char);
312
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
313
- break;
314
-
315
- case (($ord_var_c & 0xF8) == 0xF0):
316
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
317
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
318
- $char = pack('C*', $ord_var_c,
319
- ord($var{$c + 1}),
320
- ord($var{$c + 2}),
321
- ord($var{$c + 3}));
322
- $c += 3;
323
- $utf16 = $this->utf82utf16($char);
324
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
325
- break;
326
-
327
- case (($ord_var_c & 0xFC) == 0xF8):
328
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
329
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
- $char = pack('C*', $ord_var_c,
331
- ord($var{$c + 1}),
332
- ord($var{$c + 2}),
333
- ord($var{$c + 3}),
334
- ord($var{$c + 4}));
335
- $c += 4;
336
- $utf16 = $this->utf82utf16($char);
337
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
338
- break;
339
-
340
- case (($ord_var_c & 0xFE) == 0xFC):
341
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
342
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
343
- $char = pack('C*', $ord_var_c,
344
- ord($var{$c + 1}),
345
- ord($var{$c + 2}),
346
- ord($var{$c + 3}),
347
- ord($var{$c + 4}),
348
- ord($var{$c + 5}));
349
- $c += 5;
350
- $utf16 = $this->utf82utf16($char);
351
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
352
- break;
353
- }
354
- }
355
-
356
- return '"'.$ascii.'"';
357
-
358
- case 'array':
359
- /*
360
- * As per JSON spec if any array key is not an integer
361
- * we must treat the the whole array as an object. We
362
- * also try to catch a sparsely populated associative
363
- * array with numeric keys here because some JS engines
364
- * will create an array with empty indexes up to
365
- * max_index which can cause memory issues and because
366
- * the keys, which may be relevant, will be remapped
367
- * otherwise.
368
- *
369
- * As per the ECMA and JSON specification an object may
370
- * have any string as a property. Unfortunately due to
371
- * a hole in the ECMA specification if the key is a
372
- * ECMA reserved word or starts with a digit the
373
- * parameter is only accessible using ECMAScript's
374
- * bracket notation.
375
- */
376
-
377
- // treat as a JSON object
378
- if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
379
- $properties = array_map(array($this, 'name_value'),
380
- array_keys($var),
381
- array_values($var));
382
-
383
- foreach($properties as $property) {
384
- if(Services_JSON::isError($property)) {
385
- return $property;
386
- }
387
- }
388
-
389
- return '{' . join(',', $properties) . '}';
390
- }
391
-
392
- // treat it like a regular array
393
- $elements = array_map(array($this, 'encode'), $var);
394
-
395
- foreach($elements as $element) {
396
- if(Services_JSON::isError($element)) {
397
- return $element;
398
- }
399
- }
400
-
401
- return '[' . join(',', $elements) . ']';
402
-
403
- case 'object':
404
- $vars = get_object_vars($var);
405
-
406
- $properties = array_map(array($this, 'name_value'),
407
- array_keys($vars),
408
- array_values($vars));
409
-
410
- foreach($properties as $property) {
411
- if(Services_JSON::isError($property)) {
412
- return $property;
413
- }
414
- }
415
-
416
- return '{' . join(',', $properties) . '}';
417
-
418
- default:
419
- return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
420
- ? 'null'
421
- : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
422
- }
423
- }
424
-
425
- /**
426
- * array-walking function for use in generating JSON-formatted name-value pairs
427
- *
428
- * @param string $name name of key to use
429
- * @param mixed $value reference to an array element to be encoded
430
- *
431
- * @return string JSON-formatted name-value pair, like '"name":value'
432
- * @access private
433
- */
434
- function name_value($name, $value)
435
- {
436
- $encoded_value = $this->encode($value);
437
-
438
- if(Services_JSON::isError($encoded_value)) {
439
- return $encoded_value;
440
- }
441
-
442
- return $this->encode(strval($name)) . ':' . $encoded_value;
443
- }
444
-
445
- /**
446
- * reduce a string by removing leading and trailing comments and whitespace
447
- *
448
- * @param $str string string value to strip of comments and whitespace
449
- *
450
- * @return string string value stripped of comments and whitespace
451
- * @access private
452
- */
453
- function reduce_string($str)
454
- {
455
- $str = preg_replace(array(
456
-
457
- // eliminate single line comments in '// ...' form
458
- '#^\s*//(.+)$#m',
459
-
460
- // eliminate multi-line comments in '/* ... */' form, at start of string
461
- '#^\s*/\*(.+)\*/#Us',
462
-
463
- // eliminate multi-line comments in '/* ... */' form, at end of string
464
- '#/\*(.+)\*/\s*$#Us'
465
-
466
- ), '', $str);
467
-
468
- // eliminate extraneous space
469
- return trim($str);
470
- }
471
-
472
- /**
473
- * decodes a JSON string into appropriate variable
474
- *
475
- * @param string $str JSON-formatted string
476
- *
477
- * @return mixed number, boolean, string, array, or object
478
- * corresponding to given JSON input string.
479
- * See argument 1 to Services_JSON() above for object-output behavior.
480
- * Note that decode() always returns strings
481
- * in ASCII or UTF-8 format!
482
- * @access public
483
- */
484
- function decode($str)
485
- {
486
- $str = $this->reduce_string($str);
487
-
488
- switch (strtolower($str)) {
489
- case 'true':
490
- return true;
491
-
492
- case 'false':
493
- return false;
494
-
495
- case 'null':
496
- return null;
497
-
498
- default:
499
- $m = array();
500
-
501
- if (is_numeric($str)) {
502
- // Lookie-loo, it's a number
503
-
504
- // This would work on its own, but I'm trying to be
505
- // good about returning integers where appropriate:
506
- // return (float)$str;
507
-
508
- // Return float or int, as appropriate
509
- return ((float)$str == (integer)$str)
510
- ? (integer)$str
511
- : (float)$str;
512
-
513
- } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
514
- // STRINGS RETURNED IN UTF-8 FORMAT
515
- $delim = substr($str, 0, 1);
516
- $chrs = substr($str, 1, -1);
517
- $utf8 = '';
518
- $strlen_chrs = strlen($chrs);
519
-
520
- for ($c = 0; $c < $strlen_chrs; ++$c) {
521
-
522
- $substr_chrs_c_2 = substr($chrs, $c, 2);
523
- $ord_chrs_c = ord($chrs{$c});
524
-
525
- switch (true) {
526
- case $substr_chrs_c_2 == '\b':
527
- $utf8 .= chr(0x08);
528
- ++$c;
529
- break;
530
- case $substr_chrs_c_2 == '\t':
531
- $utf8 .= chr(0x09);
532
- ++$c;
533
- break;
534
- case $substr_chrs_c_2 == '\n':
535
- $utf8 .= chr(0x0A);
536
- ++$c;
537
- break;
538
- case $substr_chrs_c_2 == '\f':
539
- $utf8 .= chr(0x0C);
540
- ++$c;
541
- break;
542
- case $substr_chrs_c_2 == '\r':
543
- $utf8 .= chr(0x0D);
544
- ++$c;
545
- break;
546
-
547
- case $substr_chrs_c_2 == '\\"':
548
- case $substr_chrs_c_2 == '\\\'':
549
- case $substr_chrs_c_2 == '\\\\':
550
- case $substr_chrs_c_2 == '\\/':
551
- if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
552
- ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
553
- $utf8 .= $chrs{++$c};
554
- }
555
- break;
556
-
557
- case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
558
- // single, escaped unicode character
559
- $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
560
- . chr(hexdec(substr($chrs, ($c + 4), 2)));
561
- $utf8 .= $this->utf162utf8($utf16);
562
- $c += 5;
563
- break;
564
-
565
- case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
566
- $utf8 .= $chrs{$c};
567
- break;
568
-
569
- case ($ord_chrs_c & 0xE0) == 0xC0:
570
- // characters U-00000080 - U-000007FF, mask 110XXXXX
571
- //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
572
- $utf8 .= substr($chrs, $c, 2);
573
- ++$c;
574
- break;
575
-
576
- case ($ord_chrs_c & 0xF0) == 0xE0:
577
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
578
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
579
- $utf8 .= substr($chrs, $c, 3);
580
- $c += 2;
581
- break;
582
-
583
- case ($ord_chrs_c & 0xF8) == 0xF0:
584
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
585
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
586
- $utf8 .= substr($chrs, $c, 4);
587
- $c += 3;
588
- break;
589
-
590
- case ($ord_chrs_c & 0xFC) == 0xF8:
591
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
592
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
593
- $utf8 .= substr($chrs, $c, 5);
594
- $c += 4;
595
- break;
596
-
597
- case ($ord_chrs_c & 0xFE) == 0xFC:
598
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
599
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
600
- $utf8 .= substr($chrs, $c, 6);
601
- $c += 5;
602
- break;
603
-
604
- }
605
-
606
- }
607
-
608
- return $utf8;
609
-
610
- } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
611
- // array, or object notation
612
-
613
- if ($str{0} == '[') {
614
- $stk = array(SERVICES_JSON_IN_ARR);
615
- $arr = array();
616
- } else {
617
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
618
- $stk = array(SERVICES_JSON_IN_OBJ);
619
- $obj = array();
620
- } else {
621
- $stk = array(SERVICES_JSON_IN_OBJ);
622
- $obj = new stdClass();
623
- }
624
- }
625
-
626
- array_push($stk, array('what' => SERVICES_JSON_SLICE,
627
- 'where' => 0,
628
- 'delim' => false));
629
-
630
- $chrs = substr($str, 1, -1);
631
- $chrs = $this->reduce_string($chrs);
632
-
633
- if ($chrs == '') {
634
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
635
- return $arr;
636
-
637
- } else {
638
- return $obj;
639
-
640
- }
641
- }
642
-
643
- //print("\nparsing {$chrs}\n");
644
-
645
- $strlen_chrs = strlen($chrs);
646
-
647
- for ($c = 0; $c <= $strlen_chrs; ++$c) {
648
-
649
- $top = end($stk);
650
- $substr_chrs_c_2 = substr($chrs, $c, 2);
651
-
652
- if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
653
- // found a comma that is not inside a string, array, etc.,
654
- // OR we've reached the end of the character list
655
- $slice = substr($chrs, $top['where'], ($c - $top['where']));
656
- array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
657
- //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
658
-
659
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
660
- // we are in an array, so just push an element onto the stack
661
- array_push($arr, $this->decode($slice));
662
-
663
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
664
- // we are in an object, so figure
665
- // out the property name and set an
666
- // element in an associative array,
667
- // for now
668
- $parts = array();
669
-
670
- if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
671
- // "name":value pair
672
- $key = $this->decode($parts[1]);
673
- $val = $this->decode($parts[2]);
674
-
675
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
676
- $obj[$key] = $val;
677
- } else {
678
- $obj->$key = $val;
679
- }
680
- } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
681
- // name:value pair, where name is unquoted
682
- $key = $parts[1];
683
- $val = $this->decode($parts[2]);
684
-
685
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
686
- $obj[$key] = $val;
687
- } else {
688
- $obj->$key = $val;
689
- }
690
- }
691
-
692
- }
693
-
694
- } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
695
- // found a quote, and we are not inside a string
696
- array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
697
- //print("Found start of string at {$c}\n");
698
-
699
- } elseif (($chrs{$c} == $top['delim']) &&
700
- ($top['what'] == SERVICES_JSON_IN_STR) &&
701
- ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
702
- // found a quote, we're in a string, and it's not escaped
703
- // we know that it's not escaped becase there is _not_ an
704
- // odd number of backslashes at the end of the string so far
705
- array_pop($stk);
706
- //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
707
-
708
- } elseif (($chrs{$c} == '[') &&
709
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
710
- // found a left-bracket, and we are in an array, object, or slice
711
- array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
712
- //print("Found start of array at {$c}\n");
713
-
714
- } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
715
- // found a right-bracket, and we're in an array
716
- array_pop($stk);
717
- //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
718
-
719
- } elseif (($chrs{$c} == '{') &&
720
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
721
- // found a left-brace, and we are in an array, object, or slice
722
- array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
723
- //print("Found start of object at {$c}\n");
724
-
725
- } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
726
- // found a right-brace, and we're in an object
727
- array_pop($stk);
728
- //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
729
-
730
- } elseif (($substr_chrs_c_2 == '/*') &&
731
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
732
- // found a comment start, and we are in an array, object, or slice
733
- array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
734
- $c++;
735
- //print("Found start of comment at {$c}\n");
736
-
737
- } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
738
- // found a comment end, and we're in one now
739
- array_pop($stk);
740
- $c++;
741
-
742
- for ($i = $top['where']; $i <= $c; ++$i)
743
- $chrs = substr_replace($chrs, ' ', $i, 1);
744
-
745
- //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
746
-
747
- }
748
-
749
- }
750
-
751
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
752
- return $arr;
753
-
754
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
755
- return $obj;
756
-
757
- }
758
-
759
- }
760
- }
761
- }
762
-
763
- /**
764
- * @todo Ultimately, this should just call PEAR::isError()
765
- */
766
- function isError($data, $code = null)
767
- {
768
- if (class_exists('pear')) {
769
- return PEAR::isError($data, $code);
770
- } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
771
- is_subclass_of($data, 'services_json_error'))) {
772
- return true;
773
- }
774
-
775
- return false;
776
- }
777
- }
778
-
779
- if (class_exists('PEAR_Error')) {
780
-
781
- class Services_JSON_Error extends PEAR_Error
782
- {
783
- function Services_JSON_Error($message = 'unknown error', $code = null,
784
- $mode = null, $options = null, $userinfo = null)
785
- {
786
- parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
787
- }
788
- }
789
-
790
- } else {
791
-
792
- /**
793
- * @todo Ultimately, this class shall be descended from PEAR_Error
794
- */
795
- class Services_JSON_Error
796
- {
797
- function Services_JSON_Error($message = 'unknown error', $code = null,
798
- $mode = null, $options = null, $userinfo = null)
799
- {
800
-
801
- }
802
- }
803
-
804
- }
805
-
806
- ?>
1
+ <?php
2
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
+
4
+ /**
5
+ * Converts to and from JSON format.
6
+ *
7
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
+ * format. It is easy for humans to read and write. It is easy for machines
9
+ * to parse and generate. It is based on a subset of the JavaScript
10
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
+ * This feature can also be found in Python. JSON is a text format that is
12
+ * completely language independent but uses conventions that are familiar
13
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
14
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
+ * ideal data-interchange language.
16
+ *
17
+ * This package provides a simple encoder and decoder for JSON notation. It
18
+ * is intended for use with client-side Javascript applications that make
19
+ * use of HTTPRequest to perform server communication functions - data can
20
+ * be encoded into JSON notation for use in a client-side javascript, or
21
+ * decoded from incoming Javascript requests. JSON format is native to
22
+ * Javascript, and can be directly eval()'ed with no further parsing
23
+ * overhead
24
+ *
25
+ * All strings should be in ASCII or UTF-8 format!
26
+ *
27
+ * LICENSE: Redistribution and use in source and binary forms, with or
28
+ * without modification, are permitted provided that the following
29
+ * conditions are met: Redistributions of source code must retain the
30
+ * above copyright notice, this list of conditions and the following
31
+ * disclaimer. Redistributions in binary form must reproduce the above
32
+ * copyright notice, this list of conditions and the following disclaimer
33
+ * in the documentation and/or other materials provided with the
34
+ * distribution.
35
+ *
36
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
+ * DAMAGE.
47
+ *
48
+ * @category
49
+ * @package Services_JSON
50
+ * @author Michal Migurski <mike-json@teczno.com>
51
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
+ * @copyright 2005 Michal Migurski
54
+ * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
+ * @license http://www.opensource.org/licenses/bsd-license.php
56
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
+ */
58
+
59
+ /**
60
+ * Marker constant for Services_JSON::decode(), used to flag stack state
61
+ */
62
+ define('SERVICES_JSON_SLICE', 1);
63
+
64
+ /**
65
+ * Marker constant for Services_JSON::decode(), used to flag stack state
66
+ */
67
+ define('SERVICES_JSON_IN_STR', 2);
68
+
69
+ /**
70
+ * Marker constant for Services_JSON::decode(), used to flag stack state
71
+ */
72
+ define('SERVICES_JSON_IN_ARR', 3);
73
+
74
+ /**
75
+ * Marker constant for Services_JSON::decode(), used to flag stack state
76
+ */
77
+ define('SERVICES_JSON_IN_OBJ', 4);
78
+
79
+ /**
80
+ * Marker constant for Services_JSON::decode(), used to flag stack state
81
+ */
82
+ define('SERVICES_JSON_IN_CMT', 5);
83
+
84
+ /**
85
+ * Behavior switch for Services_JSON::decode()
86
+ */
87
+ define('SERVICES_JSON_LOOSE_TYPE', 16);
88
+
89
+ /**
90
+ * Behavior switch for Services_JSON::decode()
91
+ */
92
+ define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
+
94
+ /**
95
+ * Converts to and from JSON format.
96
+ *
97
+ * Brief example of use:
98
+ *
99
+ * <code>
100
+ * // create a new instance of Services_JSON
101
+ * $json = new Services_JSON();
102
+ *
103
+ * // convert a complexe value to JSON notation, and send it to the browser
104
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
+ * $output = $json->encode($value);
106
+ *
107
+ * print($output);
108
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
+ *
110
+ * // accept incoming POST data, assumed to be in JSON notation
111
+ * $input = file_get_contents('php://input', 1000000);
112
+ * $value = $json->decode($input);
113
+ * </code>
114
+ */
115
+ class Services_JSON
116
+ {
117
+ /**
118
+ * constructs a new JSON instance
119
+ *
120
+ * @param int $use object behavior flags; combine with boolean-OR
121
+ *
122
+ * possible values:
123
+ * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
+ * "{...}" syntax creates associative arrays
125
+ * instead of objects in decode().
126
+ * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
+ * Values which can't be encoded (e.g. resources)
128
+ * appear as NULL instead of throwing errors.
129
+ * By default, a deeply-nested resource will
130
+ * bubble up with an error, so all return values
131
+ * from encode() should be checked with isError()
132
+ */
133
+ function Services_JSON($use = 0)
134
+ {
135
+ $this->use = $use;
136
+ }
137
+
138
+ /**
139
+ * convert a string from one UTF-16 char to one UTF-8 char
140
+ *
141
+ * Normally should be handled by mb_convert_encoding, but
142
+ * provides a slower PHP-only method for installations
143
+ * that lack the multibye string extension.
144
+ *
145
+ * @param string $utf16 UTF-16 character
146
+ * @return string UTF-8 character
147
+ * @access private
148
+ */
149
+ function utf162utf8($utf16)
150
+ {
151
+ // oh please oh please oh please oh please oh please
152
+ if(function_exists('mb_convert_encoding')) {
153
+ return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
+ }
155
+
156
+ $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
157
+
158
+ switch(true) {
159
+ case ((0x7F & $bytes) == $bytes):
160
+ // this case should never be reached, because we are in ASCII range
161
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
+ return chr(0x7F & $bytes);
163
+
164
+ case (0x07FF & $bytes) == $bytes:
165
+ // return a 2-byte UTF-8 character
166
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
+ return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
+ . chr(0x80 | ($bytes & 0x3F));
169
+
170
+ case (0xFFFF & $bytes) == $bytes:
171
+ // return a 3-byte UTF-8 character
172
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
+ return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
+ . chr(0x80 | (($bytes >> 6) & 0x3F))
175
+ . chr(0x80 | ($bytes & 0x3F));
176
+ }
177
+
178
+ // ignoring UTF-32 for now, sorry
179
+ return '';
180
+ }
181
+
182
+ /**
183
+ * convert a string from one UTF-8 char to one UTF-16 char
184
+ *
185
+ * Normally should be handled by mb_convert_encoding, but
186
+ * provides a slower PHP-only method for installations
187
+ * that lack the multibye string extension.
188
+ *
189
+ * @param string $utf8 UTF-8 character
190
+ * @return string UTF-16 character
191
+ * @access private
192
+ */
193
+ function utf82utf16($utf8)
194
+ {
195
+ // oh please oh please oh please oh please oh please
196
+ if(function_exists('mb_convert_encoding')) {
197
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
+ }
199
+
200
+ switch(strlen($utf8)) {
201
+ case 1:
202
+ // this case should never be reached, because we are in ASCII range
203
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
+ return $utf8;
205
+
206
+ case 2:
207
+ // return a UTF-16 character from a 2-byte UTF-8 char
208
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
+ return chr(0x07 & (ord($utf8{0}) >> 2))
210
+ . chr((0xC0 & (ord($utf8{0}) << 6))
211
+ | (0x3F & ord($utf8{1})));
212
+
213
+ case 3:
214
+ // return a UTF-16 character from a 3-byte UTF-8 char
215
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
+ return chr((0xF0 & (ord($utf8{0}) << 4))
217
+ | (0x0F & (ord($utf8{1}) >> 2)))
218
+ . chr((0xC0 & (ord($utf8{1}) << 6))
219
+ | (0x7F & ord($utf8{2})));
220
+ }
221
+
222
+ // ignoring UTF-32 for now, sorry
223
+ return '';
224
+ }
225
+
226
+ /**
227
+ * encodes an arbitrary variable into JSON format
228
+ *
229
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
231
+ * if var is a strng, note that encode() always expects it
232
+ * to be in ASCII or UTF-8 format!
233
+ *
234
+ * @return mixed JSON string representation of input var or an error if a problem occurs
235
+ * @access public
236
+ */
237
+ function encode($var)
238
+ {
239
+ switch (gettype($var)) {
240
+ case 'boolean':
241
+ return $var ? 'true' : 'false';
242
+
243
+ case 'NULL':
244
+ return 'null';
245
+
246
+ case 'integer':
247
+ return (int) $var;
248
+
249
+ case 'double':
250
+ case 'float':
251
+ return (float) $var;
252
+
253
+ case 'string':
254
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
255
+ $ascii = '';
256
+ $strlen_var = strlen($var);
257
+
258
+ /*
259
+ * Iterate over every character in the string,
260
+ * escaping with a slash or encoding to UTF-8 where necessary
261
+ */
262
+ for ($c = 0; $c < $strlen_var; ++$c) {
263
+
264
+ $ord_var_c = ord($var{$c});
265
+
266
+ switch (true) {
267
+ case $ord_var_c == 0x08:
268
+ $ascii .= '\b';
269
+ break;
270
+ case $ord_var_c == 0x09:
271
+ $ascii .= '\t';
272
+ break;
273
+ case $ord_var_c == 0x0A:
274
+ $ascii .= '\n';
275
+ break;
276
+ case $ord_var_c == 0x0C:
277
+ $ascii .= '\f';
278
+ break;
279
+ case $ord_var_c == 0x0D:
280
+ $ascii .= '\r';
281
+ break;
282
+
283
+ case $ord_var_c == 0x22:
284
+ case $ord_var_c == 0x2F:
285
+ case $ord_var_c == 0x5C:
286
+ // double quote, slash, slosh
287
+ $ascii .= '\\'.$var{$c};
288
+ break;
289
+
290
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
291
+ // characters U-00000000 - U-0000007F (same as ASCII)
292
+ $ascii .= $var{$c};
293
+ break;
294
+
295
+ case (($ord_var_c & 0xE0) == 0xC0):
296
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
297
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
298
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
299
+ $c += 1;
300
+ $utf16 = $this->utf82utf16($char);
301
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
302
+ break;
303
+
304
+ case (($ord_var_c & 0xF0) == 0xE0):
305
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
306
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
307
+ $char = pack('C*', $ord_var_c,
308
+ ord($var{$c + 1}),
309
+ ord($var{$c + 2}));
310
+ $c += 2;
311
+ $utf16 = $this->utf82utf16($char);
312
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
313
+ break;
314
+
315
+ case (($ord_var_c & 0xF8) == 0xF0):
316
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
317
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
318
+ $char = pack('C*', $ord_var_c,
319
+ ord($var{$c + 1}),
320
+ ord($var{$c + 2}),
321
+ ord($var{$c + 3}));
322
+ $c += 3;
323
+ $utf16 = $this->utf82utf16($char);
324
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
325
+ break;
326
+
327
+ case (($ord_var_c & 0xFC) == 0xF8):
328
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
329
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
+ $char = pack('C*', $ord_var_c,
331
+ ord($var{$c + 1}),
332
+ ord($var{$c + 2}),
333
+ ord($var{$c + 3}),
334
+ ord($var{$c + 4}));
335
+ $c += 4;
336
+ $utf16 = $this->utf82utf16($char);
337
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
338
+ break;
339
+
340
+ case (($ord_var_c & 0xFE) == 0xFC):
341
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
342
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
343
+ $char = pack('C*', $ord_var_c,
344
+ ord($var{$c + 1}),
345
+ ord($var{$c + 2}),
346
+ ord($var{$c + 3}),
347
+ ord($var{$c + 4}),
348
+ ord($var{$c + 5}));
349
+ $c += 5;
350
+ $utf16 = $this->utf82utf16($char);
351
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
352
+ break;
353
+ }
354
+ }
355
+
356
+ return '"'.$ascii.'"';
357
+
358
+ case 'array':
359
+ /*
360
+ * As per JSON spec if any array key is not an integer
361
+ * we must treat the the whole array as an object. We
362
+ * also try to catch a sparsely populated associative
363
+ * array with numeric keys here because some JS engines
364
+ * will create an array with empty indexes up to
365
+ * max_index which can cause memory issues and because
366
+ * the keys, which may be relevant, will be remapped
367
+ * otherwise.
368
+ *
369
+ * As per the ECMA and JSON specification an object may
370
+ * have any string as a property. Unfortunately due to
371
+ * a hole in the ECMA specification if the key is a
372
+ * ECMA reserved word or starts with a digit the
373
+ * parameter is only accessible using ECMAScript's
374
+ * bracket notation.
375
+ */
376
+
377
+ // treat as a JSON object
378
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
379
+ $properties = array_map(array($this, 'name_value'),
380
+ array_keys($var),
381
+ array_values($var));
382
+
383
+ foreach($properties as $property) {
384
+ if(Services_JSON::isError($property)) {
385
+ return $property;
386
+ }
387
+ }
388
+
389
+ return '{' . join(',', $properties) . '}';
390
+ }
391
+
392
+ // treat it like a regular array
393
+ $elements = array_map(array($this, 'encode'), $var);
394
+
395
+ foreach($elements as $element) {
396
+ if(Services_JSON::isError($element)) {
397
+ return $element;
398
+ }
399
+ }
400
+
401
+ return '[' . join(',', $elements) . ']';
402
+
403
+ case 'object':
404
+ $vars = get_object_vars($var);
405
+
406
+ $properties = array_map(array($this, 'name_value'),
407
+ array_keys($vars),
408
+ array_values($vars));
409
+
410
+ foreach($properties as $property) {
411
+ if(Services_JSON::isError($property)) {
412
+ return $property;
413
+ }
414
+ }
415
+
416
+ return '{' . join(',', $properties) . '}';
417
+
418
+ default:
419
+ return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
420
+ ? 'null'
421
+ : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
422
+ }
423
+ }
424
+
425
+ /**
426
+ * array-walking function for use in generating JSON-formatted name-value pairs
427
+ *
428
+ * @param string $name name of key to use
429
+ * @param mixed $value reference to an array element to be encoded
430
+ *
431
+ * @return string JSON-formatted name-value pair, like '"name":value'
432
+ * @access private
433
+ */
434
+ function name_value($name, $value)
435
+ {
436
+ $encoded_value = $this->encode($value);
437
+
438
+ if(Services_JSON::isError($encoded_value)) {
439
+ return $encoded_value;
440
+ }
441
+
442
+ return $this->encode(strval($name)) . ':' . $encoded_value;
443
+ }
444
+
445
+ /**
446
+ * reduce a string by removing leading and trailing comments and whitespace
447
+ *
448
+ * @param $str string string value to strip of comments and whitespace
449
+ *
450
+ * @return string string value stripped of comments and whitespace
451
+ * @access private
452
+ */
453
+ function reduce_string($str)
454
+ {
455
+ $str = preg_replace(array(
456
+
457
+ // eliminate single line comments in '// ...' form
458
+ '#^\s*//(.+)$#m',
459
+
460
+ // eliminate multi-line comments in '/* ... */' form, at start of string
461
+ '#^\s*/\*(.+)\*/#Us',
462
+
463
+ // eliminate multi-line comments in '/* ... */' form, at end of string
464
+ '#/\*(.+)\*/\s*$#Us'
465
+
466
+ ), '', $str);
467
+
468
+ // eliminate extraneous space
469
+ return trim($str);
470
+ }
471
+
472
+ /**
473
+ * decodes a JSON string into appropriate variable
474
+ *
475
+ * @param string $str JSON-formatted string
476
+ *
477
+ * @return mixed number, boolean, string, array, or object
478
+ * corresponding to given JSON input string.
479
+ * See argument 1 to Services_JSON() above for object-output behavior.
480
+ * Note that decode() always returns strings
481
+ * in ASCII or UTF-8 format!
482
+ * @access public
483
+ */
484
+ function decode($str)
485
+ {
486
+ $str = $this->reduce_string($str);
487
+
488
+ switch (strtolower($str)) {
489
+ case 'true':
490
+ return true;
491
+
492
+ case 'false':
493
+ return false;
494
+
495
+ case 'null':
496
+ return null;
497
+
498
+ default:
499
+ $m = array();
500
+
501
+ if (is_numeric($str)) {
502
+ // Lookie-loo, it's a number
503
+
504
+ // This would work on its own, but I'm trying to be
505
+ // good about returning integers where appropriate:
506
+ // return (float)$str;
507
+
508
+ // Return float or int, as appropriate
509
+ return ((float)$str == (integer)$str)
510
+ ? (integer)$str
511
+ : (float)$str;
512
+
513
+ } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
514
+ // STRINGS RETURNED IN UTF-8 FORMAT
515
+ $delim = substr($str, 0, 1);
516
+ $chrs = substr($str, 1, -1);
517
+ $utf8 = '';
518
+ $strlen_chrs = strlen($chrs);
519
+
520
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
521
+
522
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
523
+ $ord_chrs_c = ord($chrs{$c});
524
+
525
+ switch (true) {
526
+ case $substr_chrs_c_2 == '\b':
527
+ $utf8 .= chr(0x08);
528
+ ++$c;
529
+ break;
530
+ case $substr_chrs_c_2 == '\t':
531
+ $utf8 .= chr(0x09);
532
+ ++$c;
533
+ break;
534
+ case $substr_chrs_c_2 == '\n':
535
+ $utf8 .= chr(0x0A);
536
+ ++$c;
537
+ break;
538
+ case $substr_chrs_c_2 == '\f':
539
+ $utf8 .= chr(0x0C);
540
+ ++$c;
541
+ break;
542
+ case $substr_chrs_c_2 == '\r':
543
+ $utf8 .= chr(0x0D);
544
+ ++$c;
545
+ break;
546
+
547
+ case $substr_chrs_c_2 == '\\"':
548
+ case $substr_chrs_c_2 == '\\\'':
549
+ case $substr_chrs_c_2 == '\\\\':
550
+ case $substr_chrs_c_2 == '\\/':
551
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
552
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
553
+ $utf8 .= $chrs{++$c};
554
+ }
555
+ break;
556
+
557
+ case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
558
+ // single, escaped unicode character
559
+ $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
560
+ . chr(hexdec(substr($chrs, ($c + 4), 2)));
561
+ $utf8 .= $this->utf162utf8($utf16);
562
+ $c += 5;
563
+ break;
564
+
565
+ case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
566
+ $utf8 .= $chrs{$c};
567
+ break;
568
+
569
+ case ($ord_chrs_c & 0xE0) == 0xC0:
570
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
571
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
572
+ $utf8 .= substr($chrs, $c, 2);
573
+ ++$c;
574
+ break;
575
+
576
+ case ($ord_chrs_c & 0xF0) == 0xE0:
577
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
578
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
579
+ $utf8 .= substr($chrs, $c, 3);
580
+ $c += 2;
581
+ break;
582
+
583
+ case ($ord_chrs_c & 0xF8) == 0xF0:
584
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
585
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
586
+ $utf8 .= substr($chrs, $c, 4);
587
+ $c += 3;
588
+ break;
589
+
590
+ case ($ord_chrs_c & 0xFC) == 0xF8:
591
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
592
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
593
+ $utf8 .= substr($chrs, $c, 5);
594
+ $c += 4;
595
+ break;
596
+
597
+ case ($ord_chrs_c & 0xFE) == 0xFC:
598
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
599
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
600
+ $utf8 .= substr($chrs, $c, 6);
601
+ $c += 5;
602
+ break;
603
+
604
+ }
605
+
606
+ }
607
+
608
+ return $utf8;
609
+
610
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
611
+ // array, or object notation
612
+
613
+ if ($str{0} == '[') {
614
+ $stk = array(SERVICES_JSON_IN_ARR);
615
+ $arr = array();
616
+ } else {
617
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
618
+ $stk = array(SERVICES_JSON_IN_OBJ);
619
+ $obj = array();
620
+ } else {
621
+ $stk = array(SERVICES_JSON_IN_OBJ);
622
+ $obj = new stdClass();
623
+ }
624
+ }
625
+
626
+ array_push($stk, array('what' => SERVICES_JSON_SLICE,
627
+ 'where' => 0,
628
+ 'delim' => false));
629
+
630
+ $chrs = substr($str, 1, -1);
631
+ $chrs = $this->reduce_string($chrs);
632
+
633
+ if ($chrs == '') {
634
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
635
+ return $arr;
636
+
637
+ } else {
638
+ return $obj;
639
+
640
+ }
641
+ }
642
+
643
+ //print("\nparsing {$chrs}\n");
644
+
645
+ $strlen_chrs = strlen($chrs);
646
+
647
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
648
+
649
+ $top = end($stk);
650
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
651
+
652
+ if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
653
+ // found a comma that is not inside a string, array, etc.,
654
+ // OR we've reached the end of the character list
655
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
656
+ array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
657
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
658
+
659
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
660
+ // we are in an array, so just push an element onto the stack
661
+ array_push($arr, $this->decode($slice));
662
+
663
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
664
+ // we are in an object, so figure
665
+ // out the property name and set an
666
+ // element in an associative array,
667
+ // for now
668
+ $parts = array();
669
+
670
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
671
+ // "name":value pair
672
+ $key = $this->decode($parts[1]);
673
+ $val = $this->decode($parts[2]);
674
+
675
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
676
+ $obj[$key] = $val;
677
+ } else {
678
+ $obj->$key = $val;
679
+ }
680
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
681
+ // name:value pair, where name is unquoted
682
+ $key = $parts[1];
683
+ $val = $this->decode($parts[2]);
684
+
685
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
686
+ $obj[$key] = $val;
687
+ } else {
688
+ $obj->$key = $val;
689
+ }
690
+ }
691
+
692
+ }
693
+
694
+ } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
695
+ // found a quote, and we are not inside a string
696
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
697
+ //print("Found start of string at {$c}\n");
698
+
699
+ } elseif (($chrs{$c} == $top['delim']) &&
700
+ ($top['what'] == SERVICES_JSON_IN_STR) &&
701
+ ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
702
+ // found a quote, we're in a string, and it's not escaped
703
+ // we know that it's not escaped becase there is _not_ an
704
+ // odd number of backslashes at the end of the string so far
705
+ array_pop($stk);
706
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
707
+
708
+ } elseif (($chrs{$c} == '[') &&
709
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
710
+ // found a left-bracket, and we are in an array, object, or slice
711
+ array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
712
+ //print("Found start of array at {$c}\n");
713
+
714
+ } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
715
+ // found a right-bracket, and we're in an array
716
+ array_pop($stk);
717
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
718
+
719
+ } elseif (($chrs{$c} == '{') &&
720
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
721
+ // found a left-brace, and we are in an array, object, or slice
722
+ array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
723
+ //print("Found start of object at {$c}\n");
724
+
725
+ } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
726
+ // found a right-brace, and we're in an object
727
+ array_pop($stk);
728
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
729
+
730
+ } elseif (($substr_chrs_c_2 == '/*') &&
731
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
732
+ // found a comment start, and we are in an array, object, or slice
733
+ array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
734
+ $c++;
735
+ //print("Found start of comment at {$c}\n");
736
+
737
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
738
+ // found a comment end, and we're in one now
739
+ array_pop($stk);
740
+ $c++;
741
+
742
+ for ($i = $top['where']; $i <= $c; ++$i)
743
+ $chrs = substr_replace($chrs, ' ', $i, 1);
744
+
745
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
746
+
747
+ }
748
+
749
+ }
750
+
751
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
752
+ return $arr;
753
+
754
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
755
+ return $obj;
756
+
757
+ }
758
+
759
+ }
760
+ }
761
+ }
762
+
763
+ /**
764
+ * @todo Ultimately, this should just call PEAR::isError()
765
+ */
766
+ function isError($data, $code = null)
767
+ {
768
+ if (class_exists('pear')) {
769
+ return PEAR::isError($data, $code);
770
+ } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
771
+ is_subclass_of($data, 'services_json_error'))) {
772
+ return true;
773
+ }
774
+
775
+ return false;
776
+ }
777
+ }
778
+
779
+ if (class_exists('PEAR_Error')) {
780
+
781
+ class Services_JSON_Error extends PEAR_Error
782
+ {
783
+ function Services_JSON_Error($message = 'unknown error', $code = null,
784
+ $mode = null, $options = null, $userinfo = null)
785
+ {
786
+ parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
787
+ }
788
+ }
789
+
790
+ } else {
791
+
792
+ /**
793
+ * @todo Ultimately, this class shall be descended from PEAR_Error
794
+ */
795
+ class Services_JSON_Error
796
+ {
797
+ function Services_JSON_Error($message = 'unknown error', $code = null,
798
+ $mode = null, $options = null, $userinfo = null)
799
+ {
800
+
801
+ }
802
+ }
803
+
804
+ }
805
+
806
+ ?>
lib/json/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- Redistribution and use in source and binary forms, with or without
2
- modification, are permitted provided that the following conditions are
3
- met:
4
-
5
- Redistributions of source code must retain the above copyright notice,
6
- this list of conditions and the following disclaimer.
7
-
8
- Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
11
-
12
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15
- NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ Redistribution and use in source and binary forms, with or without
2
+ modification, are permitted provided that the following conditions are
3
+ met:
4
+
5
+ Redistributions of source code must retain the above copyright notice,
6
+ this list of conditions and the following disclaimer.
7
+
8
+ Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15
+ NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lib/s3.php CHANGED
@@ -1,1967 +1,1967 @@
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) 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
+
link.class.php CHANGED
@@ -1,182 +1,182 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * link.class.php
5
- *
6
- * Manage/Add Links
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "link.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Link extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- function add_link($args)
23
- {
24
- extract($args);
25
-
26
- $params['link_url'] = esc_html($url);
27
- $params['link_url'] = esc_url($params['link_url']);
28
- $params['link_name'] = esc_html($name);
29
- $params['link_id'] = '';
30
- $params['link_description'] = $description;
31
- $params['link_target'] = $link_target;
32
- $params['link_category'] = array();
33
-
34
- //Add Link category
35
- if(is_array($link_category) && !empty($link_category)){
36
- $terms = get_terms('link_category',array('hide_empty' => 0));
37
-
38
- if($terms){
39
- foreach($terms as $term){
40
- if(in_array($term->name,$link_category)){
41
- $params['link_category'][] = $term->term_id;
42
- $link_category = $this->remove_element($link_category, $term->name);
43
- }
44
- }
45
- }
46
- if(!empty($link_category)){
47
- foreach($link_category as $linkkey => $linkval){
48
- if(!empty($linkval)){
49
- $link = wp_insert_term($linkval,'link_category');
50
-
51
- if(isset($link['term_id']) && !empty($link['term_id'])){
52
- $params['link_category'][] = $link['term_id'];
53
- }
54
- }
55
- }
56
- }
57
- }
58
-
59
- //Add Link Owner
60
- $user_obj = get_userdatabylogin($user);
61
- if($user_obj && $user_obj->ID){
62
- $params['link_owner'] = $user_obj->ID;
63
- }
64
-
65
-
66
- if(!function_exists('wp_insert_link'))
67
- include_once (ABSPATH . 'wp-admin/includes/bookmark.php');
68
-
69
- $is_success = wp_insert_link($params);
70
-
71
- return $is_success ? true : array('error' => 'Failed to add link.');
72
- }
73
-
74
- function remove_element($arr, $val){
75
- foreach ($arr as $key => $value){
76
- if ($value == $val){
77
- unset($arr[$key]);
78
- }
79
- }
80
- return $arr = array_values($arr);
81
- }
82
-
83
- function get_links($args){
84
- global $wpdb;
85
-
86
- $where='';
87
- $this->_log('MORE BRE');
88
- extract($args);
89
-
90
- if(!empty($filter_links))
91
- {
92
- $where.=" AND (link_name LIKE '%".mysql_real_escape_string($filter_links)."%' OR link_url LIKE '%".mysql_real_escape_string($filter_links)."%')";
93
- }
94
-
95
- $linkcats = $this->getLinkCats();
96
- $sql_query = "$wpdb->links WHERE 1=1 ".$where;
97
-
98
- $links_total = $wpdb->get_results("SELECT count(*) as total_links FROM ".$sql_query);
99
- $total=$links_total[0]->total_links;
100
-
101
- $query_links = $wpdb->get_results("SELECT link_id, link_url, link_name, link_target, link_visible, link_rating, link_rel FROM ".$sql_query." ORDER BY link_name ASC LIMIT 250");
102
- $links = array();
103
- foreach ( $query_links as $link_info )
104
- {
105
- $link_cat = $linkcats[$link_info->link_id];
106
- $cats = array();
107
- foreach($link_cat as $catkey=>$catval)
108
- {
109
- $cats[] = $catval;
110
- }
111
-
112
- $links[$link_info->link_id] = array(
113
- "link_url" => $link_info->link_url,
114
- "link_name" => $link_info->link_name,
115
- "link_target" => $link_info->link_target,
116
- "link_visible" => $link_info->link_visible,
117
- "link_rating" => $link_info->link_rating,
118
- "link_rel" => $link_info->link_rel,
119
- "link_cats" => $cats
120
- );
121
- }
122
-
123
- return array('links' => $links, 'total' => $total);
124
- }
125
-
126
- function getLinkCats($taxonomy = 'link_category')
127
- {
128
- global $wpdb;
129
-
130
- $cats = $wpdb->get_results("SELECT l.link_id, $wpdb->terms.name
131
- FROM $wpdb->links AS l
132
- INNER JOIN $wpdb->term_relationships ON ( l.link_id = $wpdb->term_relationships.object_id )
133
- INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
134
- AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
135
- INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
136
-
137
- foreach ( $cats as $post_val )
138
- {
139
-
140
- $post_cats[$post_val->link_id][] = $post_val->name;
141
- }
142
-
143
- return $post_cats;
144
- }
145
-
146
- function delete_link($args){
147
- global $wpdb;
148
-
149
- if(!empty($args['link_id']))
150
- {
151
- $delete_query = "DELETE FROM $wpdb->links WHERE link_id = ".$args['link_id'];
152
- $wpdb->get_results($delete_query);
153
-
154
- return 'Link deleted.';
155
- }
156
- else
157
- {
158
- return 'No ID...';
159
- }
160
- }
161
-
162
- function delete_links($args){
163
- global $wpdb;
164
- extract($args);
165
-
166
- if($deleteaction=='delete'){
167
- $delete_query_intro = "DELETE FROM $wpdb->links WHERE link_id = ";
168
- }
169
- foreach($args as $key=>$val){
170
-
171
- if(!empty($val) && is_numeric($val))
172
- {
173
- $delete_query = $delete_query_intro.$val;
174
-
175
- $wpdb->query($delete_query);
176
- }
177
- }
178
- return "Link deleted";
179
- }
180
-
181
- }
182
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * link.class.php
5
+ *
6
+ * Manage/Add Links
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "link.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Link extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ function add_link($args)
23
+ {
24
+ extract($args);
25
+
26
+ $params['link_url'] = esc_html($url);
27
+ $params['link_url'] = esc_url($params['link_url']);
28
+ $params['link_name'] = esc_html($name);
29
+ $params['link_id'] = '';
30
+ $params['link_description'] = $description;
31
+ $params['link_target'] = $link_target;
32
+ $params['link_category'] = array();
33
+
34
+ //Add Link category
35
+ if(is_array($link_category) && !empty($link_category)){
36
+ $terms = get_terms('link_category',array('hide_empty' => 0));
37
+
38
+ if($terms){
39
+ foreach($terms as $term){
40
+ if(in_array($term->name,$link_category)){
41
+ $params['link_category'][] = $term->term_id;
42
+ $link_category = $this->remove_element($link_category, $term->name);
43
+ }
44
+ }
45
+ }
46
+ if(!empty($link_category)){
47
+ foreach($link_category as $linkkey => $linkval){
48
+ if(!empty($linkval)){
49
+ $link = wp_insert_term($linkval,'link_category');
50
+
51
+ if(isset($link['term_id']) && !empty($link['term_id'])){
52
+ $params['link_category'][] = $link['term_id'];
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ //Add Link Owner
60
+ $user_obj = get_userdatabylogin($user);
61
+ if($user_obj && $user_obj->ID){
62
+ $params['link_owner'] = $user_obj->ID;
63
+ }
64
+
65
+
66
+ if(!function_exists('wp_insert_link'))
67
+ include_once (ABSPATH . 'wp-admin/includes/bookmark.php');
68
+
69
+ $is_success = wp_insert_link($params);
70
+
71
+ return $is_success ? true : array('error' => 'Failed to add link.');
72
+ }
73
+
74
+ function remove_element($arr, $val){
75
+ foreach ($arr as $key => $value){
76
+ if ($value == $val){
77
+ unset($arr[$key]);
78
+ }
79
+ }
80
+ return $arr = array_values($arr);
81
+ }
82
+
83
+ function get_links($args){
84
+ global $wpdb;
85
+
86
+ $where='';
87
+
88
+ extract($args);
89
+
90
+ if(!empty($filter_links))
91
+ {
92
+ $where.=" AND (link_name LIKE '%".mysql_real_escape_string($filter_links)."%' OR link_url LIKE '%".mysql_real_escape_string($filter_links)."%')";
93
+ }
94
+
95
+ $linkcats = $this->getLinkCats();
96
+ $sql_query = "$wpdb->links WHERE 1=1 ".$where;
97
+
98
+ $links_total = $wpdb->get_results("SELECT count(*) as total_links FROM ".$sql_query);
99
+ $total=$links_total[0]->total_links;
100
+
101
+ $query_links = $wpdb->get_results("SELECT link_id, link_url, link_name, link_target, link_visible, link_rating, link_rel FROM ".$sql_query." ORDER BY link_name ASC LIMIT 500");
102
+ $links = array();
103
+ foreach ( $query_links as $link_info )
104
+ {
105
+ $link_cat = $linkcats[$link_info->link_id];
106
+ $cats = array();
107
+ foreach($link_cat as $catkey=>$catval)
108
+ {
109
+ $cats[] = $catval;
110
+ }
111
+
112
+ $links[$link_info->link_id] = array(
113
+ "link_url" => $link_info->link_url,
114
+ "link_name" => $link_info->link_name,
115
+ "link_target" => $link_info->link_target,
116
+ "link_visible" => $link_info->link_visible,
117
+ "link_rating" => $link_info->link_rating,
118
+ "link_rel" => $link_info->link_rel,
119
+ "link_cats" => $cats
120
+ );
121
+ }
122
+
123
+ return array('links' => $links, 'total' => $total);
124
+ }
125
+
126
+ function getLinkCats($taxonomy = 'link_category')
127
+ {
128
+ global $wpdb;
129
+
130
+ $cats = $wpdb->get_results("SELECT l.link_id, $wpdb->terms.name
131
+ FROM $wpdb->links AS l
132
+ INNER JOIN $wpdb->term_relationships ON ( l.link_id = $wpdb->term_relationships.object_id )
133
+ INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
134
+ AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
135
+ INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
136
+
137
+ foreach ( $cats as $post_val )
138
+ {
139
+
140
+ $post_cats[$post_val->link_id][] = $post_val->name;
141
+ }
142
+
143
+ return $post_cats;
144
+ }
145
+
146
+ function delete_link($args){
147
+ global $wpdb;
148
+
149
+ if(!empty($args['link_id']))
150
+ {
151
+ $delete_query = "DELETE FROM $wpdb->links WHERE link_id = ".$args['link_id'];
152
+ $wpdb->get_results($delete_query);
153
+
154
+ return 'Link deleted.';
155
+ }
156
+ else
157
+ {
158
+ return 'No ID...';
159
+ }
160
+ }
161
+
162
+ function delete_links($args){
163
+ global $wpdb;
164
+ extract($args);
165
+
166
+ if($deleteaction=='delete'){
167
+ $delete_query_intro = "DELETE FROM $wpdb->links WHERE link_id = ";
168
+ }
169
+ foreach($args as $key=>$val){
170
+
171
+ if(!empty($val) && is_numeric($val))
172
+ {
173
+ $delete_query = $delete_query_intro.$val;
174
+
175
+ $wpdb->query($delete_query);
176
+ }
177
+ }
178
+ return "Link deleted";
179
+ }
180
+
181
+ }
182
  ?>
plugins/cleanup/cleanup.php CHANGED
@@ -1,222 +1,222 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- *
5
- *
6
- * ManageWP Worker Plugin
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "cleanup.php"):
13
- exit;
14
- endif;
15
- add_filter('mmb_stats_filter', 'mmb_get_extended_info');
16
-
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);
26
- $stats['num_spam_comments'] = mmb_num_spam_comments();
27
- return $stats;
28
- }
29
-
30
- /* Revisions */
31
-
32
- mmb_add_action('cleanup_delete', 'cleanup_delete_worker');
33
-
34
- 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':
46
- if (mmb_delete_all_revisions($revision_filter['revisions'])) {
47
- $return_array['revision'] = 'OK';
48
- } else {
49
- $return_array['revision_error'] = 'Failed, please try again';
50
- }
51
- break;
52
- case 'overhead':
53
- if (mmb_handle_overhead(true)) {
54
- $return_array['overhead'] = 'OK';
55
- } else {
56
- $return_array['overhead_error'] = 'Failed, please try again';
57
- }
58
- break;
59
- case 'comment':
60
- if (mmb_delete_spam_comments()) {
61
- $return_array['comment'] = 'OK';
62
- } else {
63
- $return_array['comment_error'] = 'Failed, please try again';
64
- }
65
- break;
66
- default:
67
- break;
68
- }
69
-
70
- }
71
-
72
- unset($params);
73
-
74
- mmb_response($return_array, true);
75
- }
76
-
77
- function mmb_num_revisions($filter)
78
- {
79
- global $wpdb;
80
- $sql = "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = 'revision'";
81
- $num_revisions = $wpdb->get_var($wpdb->prepare($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()
94
- {
95
- global $wpdb;
96
- $sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'revision'";
97
- $revisions = $wpdb->get_results($wpdb->prepare($sql));
98
- return $revisions;
99
- }
100
-
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($wpdb->prepare($sql));
124
-
125
- return $revisions;
126
- }
127
-
128
-
129
-
130
-
131
-
132
- /* Optimize */
133
-
134
- function mmb_handle_overhead($clear = false)
135
- {
136
- global $wpdb, $mmb_core;
137
- $tot_data = 0;
138
- $tot_idx = 0;
139
- $tot_all = 0;
140
- $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
141
- $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
142
- $total_gain = 0;
143
- $table_string = '';
144
- foreach ($tables as $table) {
145
- if (in_array($table['Engine'], array(
146
- 'MyISAM',
147
- 'ISAM',
148
- 'HEAP',
149
- 'MEMORY',
150
- 'ARCHIVE'
151
- ))) {
152
- if ($wpdb->base_prefix != $wpdb->prefix) {
153
- if (preg_match('/^' . $wpdb->prefix . '*/Ui', $table['Name'])) {
154
- if ($table['Data_free'] > 0) {
155
- $total_gain += $table['Data_free'] / 1024;
156
- $table_string .= $table['Name'] . ",";
157
- }
158
- }
159
- } else if (preg_match('/^' . $wpdb->prefix . '[0-9]{1,20}_*/Ui', $table['Name'])) {
160
- continue;
161
- } else {
162
- if ($table['Data_free'] > 0) {
163
- $total_gain += $table['Data_free'] / 1024;
164
- $table_string .= $table['Name'] . ",";
165
- }
166
- }
167
- } elseif ($table['Engine'] == 'InnoDB') {
168
- //$total_gain += $table['Data_free'] > 100*1024*1024 ? $table['Data_free'] / 1024 : 0;
169
- }
170
- }
171
-
172
- if ($clear) {
173
- $table_string = substr($table_string, 0, strlen($table_string) - 1); //remove last ,
174
-
175
- $table_string = rtrim($table_string);
176
-
177
- $query = "OPTIMIZE TABLE $table_string";
178
-
179
- $optimize = $wpdb->query($query);
180
-
181
- return $optimize === FALSE ? false : true;
182
- } else
183
- return round($total_gain, 3);
184
- }
185
-
186
-
187
-
188
-
189
- /* Spam Comments */
190
-
191
- function mmb_num_spam_comments()
192
- {
193
- global $wpdb;
194
- $sql = "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam'";
195
- $num_spams = $wpdb->get_var($wpdb->prepare($sql));
196
- return $num_spams;
197
- }
198
-
199
- function mmb_delete_spam_comments()
200
- {
201
- global $wpdb;
202
- $spams = 1;
203
- $total = 0;
204
- while ($spams) {
205
- $sql = "DELETE FROM $wpdb->comments WHERE comment_approved = 'spam' LIMIT 200";
206
- $spams = $wpdb->query($wpdb->prepare($sql));
207
- $total += $spams;
208
- if ($spams)
209
- usleep(100000);
210
- }
211
- return $total;
212
- }
213
-
214
-
215
- function mmb_get_spam_comments()
216
- {
217
- global $wpdb;
218
- $sql = "SELECT * FROM $wpdb->comments as a LEFT JOIN $wpdb->commentmeta as b WHERE a.comment_ID = b.comment_id AND a.comment_approved = 'spam'";
219
- $spams = $wpdb->get_results($wpdb->prepare($sql));
220
- return $spams;
221
- }
222
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ *
5
+ *
6
+ * ManageWP Worker Plugin
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "cleanup.php"):
13
+ exit;
14
+ endif;
15
+ add_filter('mmb_stats_filter', 'mmb_get_extended_info');
16
+
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);
26
+ $stats['num_spam_comments'] = mmb_num_spam_comments();
27
+ return $stats;
28
+ }
29
+
30
+ /* Revisions */
31
+
32
+ mmb_add_action('cleanup_delete', 'cleanup_delete_worker');
33
+
34
+ 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':
46
+ if (mmb_delete_all_revisions($revision_filter['revisions'])) {
47
+ $return_array['revision'] = 'OK';
48
+ } else {
49
+ $return_array['revision_error'] = 'Failed, please try again';
50
+ }
51
+ break;
52
+ case 'overhead':
53
+ if (mmb_handle_overhead(true)) {
54
+ $return_array['overhead'] = 'OK';
55
+ } else {
56
+ $return_array['overhead_error'] = 'Failed, please try again';
57
+ }
58
+ break;
59
+ case 'comment':
60
+ if (mmb_delete_spam_comments()) {
61
+ $return_array['comment'] = 'OK';
62
+ } else {
63
+ $return_array['comment_error'] = 'Failed, please try again';
64
+ }
65
+ break;
66
+ default:
67
+ break;
68
+ }
69
+
70
+ }
71
+
72
+ unset($params);
73
+
74
+ mmb_response($return_array, true);
75
+ }
76
+
77
+ function mmb_num_revisions($filter)
78
+ {
79
+ global $wpdb;
80
+ $sql = "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = 'revision'";
81
+ $num_revisions = $wpdb->get_var($wpdb->prepare($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()
94
+ {
95
+ global $wpdb;
96
+ $sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'revision'";
97
+ $revisions = $wpdb->get_results($wpdb->prepare($sql));
98
+ return $revisions;
99
+ }
100
+
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($wpdb->prepare($sql));
124
+
125
+ return $revisions;
126
+ }
127
+
128
+
129
+
130
+
131
+
132
+ /* Optimize */
133
+
134
+ function mmb_handle_overhead($clear = false)
135
+ {
136
+ global $wpdb, $mmb_core;
137
+ $tot_data = 0;
138
+ $tot_idx = 0;
139
+ $tot_all = 0;
140
+ $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
141
+ $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
142
+ $total_gain = 0;
143
+ $table_string = '';
144
+ foreach ($tables as $table) {
145
+ if (in_array($table['Engine'], array(
146
+ 'MyISAM',
147
+ 'ISAM',
148
+ 'HEAP',
149
+ 'MEMORY',
150
+ 'ARCHIVE'
151
+ ))) {
152
+ if ($wpdb->base_prefix != $wpdb->prefix) {
153
+ if (preg_match('/^' . $wpdb->prefix . '*/Ui', $table['Name'])) {
154
+ if ($table['Data_free'] > 0) {
155
+ $total_gain += $table['Data_free'] / 1024;
156
+ $table_string .= $table['Name'] . ",";
157
+ }
158
+ }
159
+ } else if (preg_match('/^' . $wpdb->prefix . '[0-9]{1,20}_*/Ui', $table['Name'])) {
160
+ continue;
161
+ } else {
162
+ if ($table['Data_free'] > 0) {
163
+ $total_gain += $table['Data_free'] / 1024;
164
+ $table_string .= $table['Name'] . ",";
165
+ }
166
+ }
167
+ } elseif ($table['Engine'] == 'InnoDB') {
168
+ //$total_gain += $table['Data_free'] > 100*1024*1024 ? $table['Data_free'] / 1024 : 0;
169
+ }
170
+ }
171
+
172
+ if ($clear) {
173
+ $table_string = substr($table_string, 0, strlen($table_string) - 1); //remove last ,
174
+
175
+ $table_string = rtrim($table_string);
176
+
177
+ $query = "OPTIMIZE TABLE $table_string";
178
+
179
+ $optimize = $wpdb->query($query);
180
+
181
+ return $optimize === FALSE ? false : true;
182
+ } else
183
+ return round($total_gain, 3);
184
+ }
185
+
186
+
187
+
188
+
189
+ /* Spam Comments */
190
+
191
+ function mmb_num_spam_comments()
192
+ {
193
+ global $wpdb;
194
+ $sql = "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam'";
195
+ $num_spams = $wpdb->get_var($wpdb->prepare($sql));
196
+ return $num_spams;
197
+ }
198
+
199
+ function mmb_delete_spam_comments()
200
+ {
201
+ global $wpdb;
202
+ $spams = 1;
203
+ $total = 0;
204
+ while ($spams) {
205
+ $sql = "DELETE FROM $wpdb->comments WHERE comment_approved = 'spam' LIMIT 200";
206
+ $spams = $wpdb->query($wpdb->prepare($sql));
207
+ $total += $spams;
208
+ if ($spams)
209
+ usleep(100000);
210
+ }
211
+ return $total;
212
+ }
213
+
214
+
215
+ function mmb_get_spam_comments()
216
+ {
217
+ global $wpdb;
218
+ $sql = "SELECT * FROM $wpdb->comments as a LEFT JOIN $wpdb->commentmeta as b WHERE a.comment_ID = b.comment_id AND a.comment_approved = 'spam'";
219
+ $spams = $wpdb->get_results($wpdb->prepare($sql));
220
+ return $spams;
221
+ }
222
  ?>
plugins/extra_html_example/extra_html_example.php CHANGED
@@ -1,20 +1,20 @@
1
- <?php
2
- if(basename($_SERVER['SCRIPT_FILENAME']) == "extra_html_example.php"):
3
- exit;
4
- endif;
5
- // add filter for the stats structure
6
- add_filter('mmb_stats_filter', mmb_extra_html_example);
7
-
8
- function mmb_extra_html_example($stats)
9
- {
10
- $count_posts = wp_count_posts();
11
-
12
- $published_posts = $count_posts->publish;
13
-
14
- // add 'extra_html' element. This is what gets displayed in the dashboard
15
- $stats['extra_html'] = '<p>Hello from '.get_bloginfo('name').' with '.$published_posts.' published posts.</p>';
16
-
17
- // return the whole array back
18
- return $stats;
19
- }
20
  ?>
1
+ <?php
2
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "extra_html_example.php"):
3
+ exit;
4
+ endif;
5
+ // add filter for the stats structure
6
+ add_filter('mmb_stats_filter', mmb_extra_html_example);
7
+
8
+ function mmb_extra_html_example($stats)
9
+ {
10
+ $count_posts = wp_count_posts();
11
+
12
+ $published_posts = $count_posts->publish;
13
+
14
+ // add 'extra_html' element. This is what gets displayed in the dashboard
15
+ $stats['extra_html'] = '<p>Hello from '.get_bloginfo('name').' with '.$published_posts.' published posts.</p>';
16
+
17
+ // return the whole array back
18
+ return $stats;
19
+ }
20
  ?>
plugins/search/search.php CHANGED
@@ -1,132 +1,132 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * stats.class.php
5
- *
6
- * Various searches on worker
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "search.php"):
13
- exit;
14
- endif;
15
- mmb_add_action('search_posts_by_term', 'search_posts_by_term');
16
-
17
- function search_posts_by_term($params = false){
18
-
19
- global $wpdb, $current_user;
20
-
21
- $search_type = trim($params['search_type']);
22
- $search_term = strtolower(trim($params['search_term']));
23
- switch ($search_type){
24
- case 'page_post':
25
- $num_posts = 10;
26
- $num_content_char = 30;
27
-
28
- $term_orig = trim($params['search_term']);
29
-
30
- $term_base= addslashes(trim($params['search_term']));
31
-
32
- $query = "SELECT *
33
- FROM $wpdb->posts
34
- WHERE $wpdb->posts.post_status = 'publish'
35
- AND ($wpdb->posts.post_title LIKE '%$term_base%'
36
- OR $wpdb->posts.post_content LIKE '%$term_base%')
37
- ORDER BY $wpdb->posts.post_modified DESC
38
- LIMIT 0, $num_posts
39
- ";
40
-
41
- $posts_array = $wpdb->get_results($query);
42
-
43
- $ret_posts = array();
44
-
45
- foreach($posts_array as $post){
46
- //highlight searched term
47
-
48
- if (substr_count(strtolower($post->post_title), strtolower($term_orig))){
49
- $str_position_start = strpos(strtolower($post->post_title), strtolower($term_orig));
50
-
51
- $post->post_title = substr($post->post_title, 0, $str_position_start).'<b>'.
52
- substr($post->post_title, $str_position_start, strlen($term_orig)).'</b>'.
53
- substr($post->post_title, $str_position_start + strlen($term_orig));
54
-
55
- }
56
- $post->post_content = html_entity_decode($post->post_content);
57
-
58
- $post->post_content = strip_tags($post->post_content);
59
-
60
-
61
-
62
- if (substr_count(strtolower($post->post_content), strtolower($term_orig))){
63
- $str_position_start = strpos(strtolower($post->post_content), strtolower($term_orig));
64
-
65
- $start = $str_position_start > $num_content_char ? $str_position_start - $num_content_char: 0;
66
- $first_len = $str_position_start > $num_content_char? $num_content_char : $str_position_start;
67
-
68
- $start_substring = $start>0 ? '...' : '';
69
- $post->post_content = $start_substring . substr($post->post_content, $start, $first_len).'<b>'.
70
- substr($post->post_content, $str_position_start, strlen($term_orig)).'</b>'.
71
- substr($post->post_content, $str_position_start + strlen($term_orig), $num_content_char) . '...';
72
-
73
-
74
- }else{
75
- $post->post_content = substr($post->post_content,0, 50). '...';
76
- }
77
-
78
- $ret_posts[] = array(
79
- 'ID' => $post->ID
80
- ,'post_permalink' => get_permalink($post->ID)
81
- ,'post_date' => $post->post_date
82
- ,'post_title' => $post->post_title
83
- ,'post_content' => $post->post_content
84
- ,'post_modified' => $post->post_modified
85
- ,'comment_count' => $post->comment_count
86
-
87
-
88
- );
89
- }
90
- mmb_response($ret_posts, true);
91
- break;
92
-
93
- case 'plugin':
94
- $plugins = get_option('active_plugins');
95
-
96
- if(!function_exists('get_plugin_data'))
97
- include_once( ABSPATH.'/wp-admin/includes/plugin.php');
98
-
99
- $have_plugin = array();
100
- foreach ($plugins as $plugin) {
101
- $pl = WP_PLUGIN_DIR . '/' . $plugin ;
102
- $pl_extended = get_plugin_data($pl);
103
- $pl_name = $pl_extended['Name'];
104
- if(strpos(strtolower($pl_name), $search_term)>-1){
105
-
106
- $have_plugin[] = $pl_name;
107
- }
108
- }
109
- if($have_plugin){
110
- mmb_response($have_plugin, true);
111
- }else{
112
- mmb_response('Not found', false);
113
- }
114
- break;
115
- case 'theme':
116
- $theme = strtolower(get_option('stylesheet'));
117
- $tm = ABSPATH . 'wp-content/themes/'. $theme . '/style.css' ;
118
- $tm_extended = get_theme_data($tm);
119
- $tm_name = $tm_extended['Name'];
120
- $have_theme = array();
121
- if(strpos(strtolower($tm_name), $search_term)>-1){
122
- $have_theme[] = $tm_name;
123
- mmb_response($have_theme, true);
124
- }else{
125
- mmb_response('Not found', false);
126
- }
127
- break;
128
- default: mmb_response('Not found', false);
129
- }
130
- }
131
-
132
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * stats.class.php
5
+ *
6
+ * Various searches on worker
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "search.php"):
13
+ exit;
14
+ endif;
15
+ mmb_add_action('search_posts_by_term', 'search_posts_by_term');
16
+
17
+ function search_posts_by_term($params = false){
18
+
19
+ global $wpdb, $current_user;
20
+
21
+ $search_type = trim($params['search_type']);
22
+ $search_term = strtolower(trim($params['search_term']));
23
+ switch ($search_type){
24
+ case 'page_post':
25
+ $num_posts = 10;
26
+ $num_content_char = 30;
27
+
28
+ $term_orig = trim($params['search_term']);
29
+
30
+ $term_base= addslashes(trim($params['search_term']));
31
+
32
+ $query = "SELECT *
33
+ FROM $wpdb->posts
34
+ WHERE $wpdb->posts.post_status = 'publish'
35
+ AND ($wpdb->posts.post_title LIKE '%$term_base%'
36
+ OR $wpdb->posts.post_content LIKE '%$term_base%')
37
+ ORDER BY $wpdb->posts.post_modified DESC
38
+ LIMIT 0, $num_posts
39
+ ";
40
+
41
+ $posts_array = $wpdb->get_results($query);
42
+
43
+ $ret_posts = array();
44
+
45
+ foreach($posts_array as $post){
46
+ //highlight searched term
47
+
48
+ if (substr_count(strtolower($post->post_title), strtolower($term_orig))){
49
+ $str_position_start = strpos(strtolower($post->post_title), strtolower($term_orig));
50
+
51
+ $post->post_title = substr($post->post_title, 0, $str_position_start).'<b>'.
52
+ substr($post->post_title, $str_position_start, strlen($term_orig)).'</b>'.
53
+ substr($post->post_title, $str_position_start + strlen($term_orig));
54
+
55
+ }
56
+ $post->post_content = html_entity_decode($post->post_content);
57
+
58
+ $post->post_content = strip_tags($post->post_content);
59
+
60
+
61
+
62
+ if (substr_count(strtolower($post->post_content), strtolower($term_orig))){
63
+ $str_position_start = strpos(strtolower($post->post_content), strtolower($term_orig));
64
+
65
+ $start = $str_position_start > $num_content_char ? $str_position_start - $num_content_char: 0;
66
+ $first_len = $str_position_start > $num_content_char? $num_content_char : $str_position_start;
67
+
68
+ $start_substring = $start>0 ? '...' : '';
69
+ $post->post_content = $start_substring . substr($post->post_content, $start, $first_len).'<b>'.
70
+ substr($post->post_content, $str_position_start, strlen($term_orig)).'</b>'.
71
+ substr($post->post_content, $str_position_start + strlen($term_orig), $num_content_char) . '...';
72
+
73
+
74
+ }else{
75
+ $post->post_content = substr($post->post_content,0, 50). '...';
76
+ }
77
+
78
+ $ret_posts[] = array(
79
+ 'ID' => $post->ID
80
+ ,'post_permalink' => get_permalink($post->ID)
81
+ ,'post_date' => $post->post_date
82
+ ,'post_title' => $post->post_title
83
+ ,'post_content' => $post->post_content
84
+ ,'post_modified' => $post->post_modified
85
+ ,'comment_count' => $post->comment_count
86
+
87
+
88
+ );
89
+ }
90
+ mmb_response($ret_posts, true);
91
+ break;
92
+
93
+ case 'plugin':
94
+ $plugins = get_option('active_plugins');
95
+
96
+ if(!function_exists('get_plugin_data'))
97
+ include_once( ABSPATH.'/wp-admin/includes/plugin.php');
98
+
99
+ $have_plugin = array();
100
+ foreach ($plugins as $plugin) {
101
+ $pl = WP_PLUGIN_DIR . '/' . $plugin ;
102
+ $pl_extended = get_plugin_data($pl);
103
+ $pl_name = $pl_extended['Name'];
104
+ if(strpos(strtolower($pl_name), $search_term)>-1){
105
+
106
+ $have_plugin[] = $pl_name;
107
+ }
108
+ }
109
+ if($have_plugin){
110
+ mmb_response($have_plugin, true);
111
+ }else{
112
+ mmb_response('Not found', false);
113
+ }
114
+ break;
115
+ case 'theme':
116
+ $theme = strtolower(get_option('stylesheet'));
117
+ $tm = ABSPATH . 'wp-content/themes/'. $theme . '/style.css' ;
118
+ $tm_extended = get_theme_data($tm);
119
+ $tm_name = $tm_extended['Name'];
120
+ $have_theme = array();
121
+ if(strpos(strtolower($tm_name), $search_term)>-1){
122
+ $have_theme[] = $tm_name;
123
+ mmb_response($have_theme, true);
124
+ }else{
125
+ mmb_response('Not found', false);
126
+ }
127
+ break;
128
+ default: mmb_response('Not found', false);
129
+ }
130
+ }
131
+
132
  ?>
post.class.php CHANGED
@@ -1,685 +1,689 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * post.class.php
5
- *
6
- * Create remote post
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "post.class.php"):
13
- exit;
14
- endif;
15
- class MMB_Post extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- function create($args)
23
- {
24
-
25
- $this->_log($args);
26
- global $wpdb;
27
-
28
- /**
29
- * algorithm
30
- * 1. create post using wp_insert_post (insert tags also here itself)
31
- * 2. use wp_create_categories() to create(not exists) and insert in the post
32
- * 3. insert meta values
33
- */
34
-
35
- include_once ABSPATH . 'wp-admin/includes/taxonomy.php';
36
- include_once ABSPATH . 'wp-admin/includes/image.php';
37
- include_once ABSPATH . 'wp-admin/includes/file.php';
38
-
39
- $post_struct = $args['post_data'];
40
-
41
- $post_data = $post_struct['post_data'];
42
- $new_custom = $post_struct['post_extras']['post_meta'];
43
- $post_categories = explode(',', $post_struct['post_extras']['post_categories']);
44
- $post_atta_img = $post_struct['post_extras']['post_atta_images'];
45
- $post_upload_dir = $post_struct['post_extras']['post_upload_dir'];
46
- $post_checksum = $post_struct['post_extras']['post_checksum'];
47
- $post_featured_img = $post_struct['post_extras']['featured_img'];
48
-
49
- $upload = wp_upload_dir();
50
-
51
- // create dynamic url RegExp
52
- $mwp_base_url = parse_url($post_upload_dir['url']);
53
- $mwp_regexp_url = $mwp_base_url['host'] . $mwp_base_url['path'];
54
- $rep = array(
55
- '/',
56
- '+',
57
- '.',
58
- ':',
59
- '?'
60
- );
61
- $with = array(
62
- '\/',
63
- '\+',
64
- '\.',
65
- '\:',
66
- '\?'
67
- );
68
- $mwp_regexp_url = str_replace($rep, $with, $mwp_regexp_url);
69
-
70
- // rename all src ../wp-content/ with hostname/wp-content/
71
- $mmb_dot_url = '..' . $mmb_base_url['path'];
72
- $mmb_dot_url = str_replace($rep, $with, $mmb_dot_url);
73
- $dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
74
- if ($dot_match_count > 0) {
75
- foreach ($dot_get_urls as $dot_url) {
76
- $match_dot = '/' . str_replace($rep, $with, $dot_url[4]) . '/';
77
- $replace_dot = 'http://' . $mmb_base_url['host'] . substr($dot_url[4], 2, strlen($dot_url[4]));
78
- $post_data['post_content'] = preg_replace($match_dot, $replace_dot, $post_data['post_content']);
79
-
80
- if ($dot_url[1] != '') {
81
- $match_dot_a = '/' . str_replace($rep, $with, $dot_url[2]) . '/';
82
- $replace_dot_a = 'http://' . $mmb_base_url['host'] . substr($dot_url[2], 2, strlen($dot_url[2]));
83
- $post_data['post_content'] = preg_replace($match_dot_a, $replace_dot_a, $post_data['post_content']);
84
- }
85
- }
86
- }
87
-
88
-
89
-
90
- //to find all the images
91
- $match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]+' . $mmb_regexp_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $get_urls, PREG_SET_ORDER);
92
- if ($match_count > 0) {
93
- $attachments = array();
94
- $post_content = $post_data['post_content'];
95
-
96
- foreach ($get_urls as $get_url_k => $get_url) {
97
- // unset url in attachment array
98
- foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
99
- $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
100
- if (preg_match($match_patt_url, $get_url[4])) {
101
- unset($post_atta_img[$atta_url_k]);
102
- }
103
- }
104
-
105
- if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
106
- if ($get_url[1] != '') {
107
- // change src url
108
- $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
109
-
110
- $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
111
- $s_mmb_rp = $s_img_atta[0];
112
- $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
113
- // change attachment url
114
- if (preg_match('/attachment_id/i', $get_url[2])) {
115
- $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
116
- $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
117
- $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
118
- }
119
- }
120
- continue;
121
- }
122
-
123
- $no_thumb = '';
124
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
125
- $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
126
- } else {
127
- $no_thumb = $get_url[4];
128
- }
129
-
130
- if(isset($upload['error']) && !empty($upload['error'])){
131
- return array('error' => $upload['error']);
132
- }
133
- $file_name = basename($no_thumb);
134
- $tmp_file = download_url($no_thumb);
135
-
136
- if(is_wp_error($tmp_file)){
137
- return array('error' => $tmp_file->get_error_message());
138
- }
139
-
140
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
141
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
142
- $renamed = @rename($tmp_file, $attach_upload['path']);
143
- if ($renamed === true) {
144
- $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
145
- $replace_pattern = $attach_upload['url'];
146
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
147
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
148
- $match_pattern = '/' . str_replace($rep, $with, preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4])) . '/';
149
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
150
- }
151
-
152
- $attachment = array(
153
- 'post_title' => $file_name,
154
- 'post_content' => '',
155
- 'post_type' => 'attachment',
156
- //'post_parent' => $post_id,
157
- 'post_mime_type' => 'image/' . $get_url[5],
158
- 'guid' => $attach_upload['url']
159
- );
160
-
161
- // Save the data
162
-
163
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
164
-
165
- $attachments[$attach_id] = 0;
166
-
167
- // featured image
168
- if ($post_featured_img != '') {
169
- $feat_img_url = '';
170
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
171
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
172
- } else {
173
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
174
- }
175
- $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
176
- if (preg_match($m_feat_url, $get_url[4])) {
177
- $post_featured_img = '';
178
- $attachments[$attach_id] = $attach_id;
179
- }
180
- }
181
-
182
- // set $get_urls value[6] - parent atta_id
183
- foreach ($get_urls as $url_k => $url_v) {
184
- if ($get_url_k != $url_k) {
185
- $s_get_url = '';
186
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
187
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
188
- } else {
189
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
190
- }
191
- $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
192
- if (preg_match($m_patt_url, $get_url[4])) {
193
- array_push($get_urls[$url_k], $attach_id);
194
- }
195
- }
196
- }
197
-
198
-
199
- $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
200
- wp_update_attachment_metadata($attach_id, $some_data);
201
-
202
-
203
- // changing href of a tag
204
- if ($get_url[1] != '') {
205
- $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
206
- if (preg_match('/attachment_id/i', $get_url[2])) {
207
- $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
208
- $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
209
- }
210
- }
211
- } else {
212
- @unlink($tmp_file);
213
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
214
-
215
- }
216
- @unlink($tmp_file);
217
- }
218
-
219
-
220
- $post_data['post_content'] = $post_content;
221
-
222
- }
223
- if (count($post_atta_img)) {
224
- foreach ($post_atta_img as $img) {
225
- $file_name = basename($img['src']);
226
-
227
- if(isset($upload['error']) && !empty($upload['error'])){
228
- return array('error' => $upload['error']);
229
- }
230
-
231
- $tmp_file = download_url($img['src']);
232
- if(is_wp_error($tmp_file)){
233
- return array('error' => $tmp_file->get_error_message());
234
- }
235
-
236
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
237
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
238
- $renamed = @rename($tmp_file, $attach_upload['path']);
239
- if ($renamed === true) {
240
- $atta_ext = end(explode('.', $file_name));
241
-
242
- $attachment = array(
243
- 'post_title' => $file_name,
244
- 'post_content' => '',
245
- 'post_type' => 'attachment',
246
- //'post_parent' => $post_id,
247
- 'post_mime_type' => 'image/' . $atta_ext,
248
- 'guid' => $attach_upload['url']
249
- );
250
-
251
- // Save the data
252
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
253
- wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
254
- $attachments[$attach_id] = 0;
255
-
256
- // featured image
257
- if ($post_featured_img != '') {
258
- $feat_img_url = '';
259
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
260
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
261
- } else {
262
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
263
- }
264
- $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
265
- if (preg_match($m_feat_url, $img['src'])) {
266
- $post_featured_img = '';
267
- $attachments[$attach_id] = $attach_id;
268
- }
269
- }
270
-
271
- } else {
272
- @unlink($tmp_file);
273
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
274
- }
275
- @unlink($tmp_file);
276
- }
277
- }
278
-
279
- //Prepare post data and temporarily remove content filters before insert post
280
- $user = $this->mmb_get_user_info( $args['username'] );
281
- if($user && $user->ID){
282
- $post_data['post_author'] = $user->ID;
283
- }
284
- //remove filter which can brake scripts or html
285
- remove_filter('content_save_pre', 'wp_filter_post_kses');
286
-
287
- //check for edit post
288
- $post_result = 0;
289
- if(isset($post_data['mwp_post_edit']) && $post_data['mwp_post_edit']){
290
-
291
-
292
- if($post_data['mwp_match_by'] == 'title'){
293
- $match_by = "post_title = '".$post_data['post_title']."'";
294
- } else {
295
- $match_by = "post_name = '".$post_data['post_name']."'";
296
- }
297
-
298
- $query = "SELECT ID FROM $wpdb->posts WHERE $match_by AND post_status NOT IN('inherit','auto-draft','draft') LIMIT 1";
299
-
300
- $post_result = $wpdb->get_var($query);
301
-
302
- }
303
-
304
-
305
- if($post_result){
306
- //update existing post
307
- $post_data['ID'] = $post_result;
308
- $post_id = wp_update_post($post_data);
309
-
310
- //check for previous attachments
311
- $atta_allimages =& get_children('post_type=attachment&post_parent=' . $post_id);
312
- if (!empty($atta_allimages)) {
313
- foreach ($atta_allimages as $image) {
314
- wp_delete_attachment($image->ID);
315
- }
316
- }
317
-
318
- } else {
319
- if($post_data['mwp_post_edit'] && $post_data['mwp_force_publish']){
320
- $post_id = wp_insert_post($post_data);
321
- } elseif($post_data['mwp_post_edit'] && !$post_data['mwp_force_publish']) {
322
- return array('error' => "Post not found.");
323
- } else {
324
- $post_id = wp_insert_post($post_data);
325
- }
326
-
327
- }
328
-
329
- if (count($attachments)) {
330
- foreach ($attachments as $atta_id => $featured_id) {
331
- $result = wp_update_post(array(
332
- 'ID' => $atta_id,
333
- 'post_parent' => $post_id
334
- ));
335
- if ($featured_id > 0) {
336
- $new_custom['_thumbnail_id'] = array(
337
- $featured_id
338
- );
339
- }
340
- }
341
- }
342
-
343
- // featured image
344
- if ($post_featured_img != '') {
345
- $file_name = basename($post_featured_img);
346
- if(isset($upload['error']) && !empty($upload['error'])){
347
- return array('error' => $upload['error']);
348
- }
349
- $tmp_file = download_url($post_featured_img);
350
- if(is_wp_error($tmp_file)){
351
- return array('error' => $tmp_file->get_error_message());
352
- }
353
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
354
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
355
- $renamed = @rename($tmp_file, $attach_upload['path']);
356
- if ($renamed === true) {
357
- $atta_ext = end(explode('.', $file_name));
358
-
359
- $attachment = array(
360
- 'post_title' => $file_name,
361
- 'post_content' => '',
362
- 'post_type' => 'attachment',
363
- 'post_parent' => $post_id,
364
- 'post_mime_type' => 'image/' . $atta_ext,
365
- 'guid' => $attach_upload['url']
366
- );
367
-
368
- // Save the data
369
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
370
- wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
371
- $new_custom['_thumbnail_id'] = array(
372
- $attach_id
373
- );
374
- } else {
375
- @unlink($tmp_file);
376
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
377
- }
378
- @unlink($tmp_file);
379
- }
380
-
381
- if ($post_id && is_array($post_categories)) {
382
- //insert categories
383
-
384
- $cat_ids = wp_create_categories($post_categories, $post_id);
385
- }
386
-
387
-
388
- //get current custom fields
389
- $cur_custom = get_post_custom($post_id);
390
- //check which values doesnot exists in new custom fields
391
- $diff_values = array_diff_key($cur_custom, $new_custom);
392
-
393
- if (is_array($diff_values))
394
- foreach ($diff_values as $meta_key => $value) {
395
- delete_post_meta($post_id, $meta_key);
396
- }
397
- //insert new post meta
398
- foreach ($new_custom as $meta_key => $value) {
399
- if (strpos($meta_key, '_mmb') === 0 || strpos($meta_key, '_edit') === 0) {
400
- continue;
401
- } else {
402
- update_post_meta($post_id, $meta_key, $value[0]);
403
- }
404
- }
405
- return $post_id;
406
- }
407
-
408
-
409
- function change_status($args)
410
- {
411
-
412
- global $wpdb;
413
- $post_id = $args['post_id'];
414
- $status = $args['status'];
415
- $success = false;
416
-
417
- if(in_array($status, array('draft', 'publish', 'trash'))){
418
- $sql = "update ".$wpdb->prefix."posts set post_status = '$status' where ID = '$post_id'";
419
- $success = $wpdb->query($sql);
420
- }
421
-
422
- return $success;
423
- }
424
-
425
- function get_posts($args){
426
- global $wpdb;
427
-
428
- $where='';
429
-
430
- extract($args);
431
-
432
- if(!empty($filter_posts))
433
- {
434
- $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_posts)."%'";
435
- }
436
-
437
- if(!empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
438
- {
439
- $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_posts_date_from)."' AND '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
440
- }
441
- else if(!empty($mwp_get_posts_date_from) && empty($mwp_get_posts_date_to))
442
- {
443
- $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_posts_date_from)."'";
444
- }
445
- else if(empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
446
- {
447
- $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
448
- }
449
- $post_array=array();
450
- $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
451
- foreach ($args as $checkbox => $checkbox_val)
452
- {
453
- if($checkbox_val=="on") {
454
- $post_array[]="'".str_replace("mwp_get_posts_","",$checkbox)."'";
455
- }
456
- }
457
- if(!empty($post_array))
458
- {
459
- $where.=" AND post_status IN (".implode(",",$post_array).")";
460
- }
461
-
462
- $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' ".$where." ORDER BY post_date DESC";
463
-
464
- $total = array();
465
- $user_info = $this->getUsersIDs();
466
- $post_cats=$this->getPostCats();
467
- $post_tags=$this->getPostCats('post_tag');
468
- $posts_total = $wpdb->get_results("SELECT count(*) as total_posts FROM ".$sql_query);
469
- $total['total_num']=$posts_total[0]->total_posts;
470
-
471
- $posts = array();
472
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query." LIMIT 250");
473
-
474
- foreach ( $posts_info as $post_info )
475
- {
476
-
477
- $cats=array();
478
- foreach($post_cats[$post_info->ID] as $cat_array => $cat_array_val)
479
- {
480
- $cats[] = array('name' => $cat_array_val);
481
- }
482
-
483
- $tags=array();
484
- foreach($post_tags[$post_info->ID] as $tag_array => $tag_array_val)
485
- {
486
- $tags[] = array('name' => $tag_array_val);
487
- }
488
-
489
- $posts[]=array(
490
- 'post_id'=>$post_info->ID,
491
- 'post_title'=>$post_info->post_title,
492
- 'post_name'=>$post_info->post_name,
493
- 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
494
- 'post_date'=>$post_info->post_date,
495
- 'post_modified'=>$post_info->post_modified,
496
- 'post_status'=>$post_info->post_status,
497
- 'post_type'=>$post_info->post_type,
498
- 'guid'=>$post_info->guid,
499
- 'post_password'=>$post_info->post_password,
500
- 'ping_status'=>$post_info->ping_status,
501
- 'comment_status'=>$post_info->comment_status,
502
- 'comment_count'=>$post_info->comment_count,
503
- 'cats'=>$cats,
504
- 'tags'=>$tags,
505
-
506
- );
507
- }
508
-
509
- return array('posts' => $posts, 'total' => $total);
510
- }
511
-
512
- function delete_post($args){
513
- global $wpdb;
514
- if(!empty($args['post_id']) && !empty($args['action']))
515
- {
516
- if($args['action']=='delete')
517
- {
518
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
519
- }
520
- else if($args['action']=='delete_perm'){
521
- $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
522
- }
523
- else if($args['action']=='delete_restore'){
524
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
525
- }
526
- $wpdb->get_results($delete_query);
527
-
528
- return 'Post deleted.';
529
- }
530
- else
531
- {
532
- return 'No ID...';
533
- }
534
- }
535
-
536
- function delete_posts($args){
537
- global $wpdb;
538
- extract($args);
539
- if($deleteaction=='delete'){
540
- $delete_query_intro = "DELETE FROM $wpdb->posts WHERE ID = ";
541
- }elseif($deleteaction=='trash'){
542
- $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ";
543
- }
544
- foreach($args as $key=>$val){
545
-
546
- if(!empty($val) && is_numeric($val))
547
- {
548
- $delete_query = $delete_query_intro.$val;
549
-
550
- $wpdb->query($delete_query);
551
- }
552
- }
553
- return "Post deleted";
554
-
555
- }
556
-
557
- function get_pages($args){
558
- global $wpdb;
559
-
560
- $where='';
561
- extract($args);
562
-
563
- if(!empty($filter_pages))
564
- {
565
- $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_pages)."%'";
566
- }
567
- if(!empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
568
- {
569
- $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_pages_date_from)."' AND '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
570
- }
571
- else if(!empty($mwp_get_pages_date_from) && empty($mwp_get_pages_date_to))
572
- {
573
- $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_pages_date_from)."'";
574
- }
575
- else if(empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
576
- {
577
- $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
578
- }
579
-
580
- $post_array=array();
581
- $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
582
- foreach ($args as $checkbox => $checkbox_val)
583
- {
584
- if($checkbox_val=="on") {
585
- $post_array[]="'".str_replace("mwp_get_pages_","",$checkbox)."'";
586
- }
587
- }
588
- if(!empty($post_array))
589
- {
590
- $where.=" AND post_status IN (".implode(",",$post_array).")";
591
- }
592
-
593
- $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='page' ".$where.' ORDER BY post_date DESC';
594
-
595
- $total = array();
596
- $user_info = $this->getUsersIDs();
597
- $posts_total = $wpdb->get_results("SELECT count(*) as total_posts FROM ".$sql_query);
598
- $total['total_num']=$posts_total[0]->total_posts;
599
-
600
- $posts = array();
601
- $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query." LIMIT 250");
602
-
603
- foreach ( $posts_info as $post_info )
604
- {
605
-
606
- $posts[]=array(
607
- 'post_id'=>$post_info->ID,
608
- 'post_title'=>$post_info->post_title,
609
- 'post_name'=>$post_info->post_name,
610
- 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
611
- 'post_date'=>$post_info->post_date,
612
- 'post_modified'=>$post_info->post_modified,
613
- 'post_status'=>$post_info->post_status,
614
- 'post_type'=>$post_info->post_type,
615
- 'guid'=>$post_info->guid,
616
- 'post_password'=>$post_info->post_password,
617
- 'ping_status'=>$post_info->ping_status,
618
- 'comment_status'=>$post_info->comment_status,
619
- 'comment_count'=>$post_info->comment_count
620
-
621
- );
622
- }
623
-
624
- return array('posts' => $posts, 'total' => $total);
625
- }
626
-
627
- function delete_page($args){
628
- global $wpdb;
629
- if(!empty($args['post_id']) && !empty($args['action']))
630
- {
631
- if($args['action']=='delete')
632
- {
633
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
634
- }
635
- else if($args['action']=='delete_perm'){
636
- $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
637
- }
638
- else if($args['action']=='delete_restore'){
639
- $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
640
- }
641
- $wpdb->get_results($delete_query);
642
-
643
- return 'Page deleted.';
644
- }
645
- else
646
- {
647
- return 'No ID...';
648
- }
649
- }
650
-
651
- function getPostCats($taxonomy = 'category')
652
- {
653
- global $wpdb;
654
-
655
- $cats = $wpdb->get_results("SELECT p.ID AS post_id, $wpdb->terms.name
656
- FROM $wpdb->posts AS p
657
- INNER JOIN $wpdb->term_relationships ON ( p.ID = $wpdb->term_relationships.object_id )
658
- INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
659
- AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
660
- INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
661
-
662
- foreach ( $cats as $post_val )
663
- {
664
-
665
- $post_cats[$post_val->post_id][] = $post_val->name;
666
- }
667
-
668
- return $post_cats;
669
- }
670
-
671
- function getUsersIDs()
672
- {
673
- global $wpdb;
674
- $users_authors=array();
675
- $users = $wpdb->get_results("SELECT ID as user_id, display_name FROM $wpdb->users WHERE user_status=0");
676
-
677
- foreach ( $users as $user_key=>$user_val )
678
- {
679
- $users_authors[$user_val->user_id] = $user_val->display_name;
680
- }
681
-
682
- return $users_authors;
683
- }
684
- }
 
 
 
 
685
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * post.class.php
5
+ *
6
+ * Create remote post
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "post.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_Post extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ function create($args)
23
+ {
24
+
25
+ //$this->_log($args);
26
+ global $wpdb;
27
+
28
+ /**
29
+ * algorithm
30
+ * 1. create post using wp_insert_post (insert tags also here itself)
31
+ * 2. use wp_create_categories() to create(not exists) and insert in the post
32
+ * 3. insert meta values
33
+ */
34
+
35
+ include_once ABSPATH . 'wp-admin/includes/taxonomy.php';
36
+ include_once ABSPATH . 'wp-admin/includes/image.php';
37
+ include_once ABSPATH . 'wp-admin/includes/file.php';
38
+
39
+ $post_struct = $args['post_data'];
40
+
41
+ $post_data = $post_struct['post_data'];
42
+ $new_custom = $post_struct['post_extras']['post_meta'];
43
+ $post_categories = explode(',', $post_struct['post_extras']['post_categories']);
44
+ $post_atta_img = $post_struct['post_extras']['post_atta_images'];
45
+ $post_upload_dir = $post_struct['post_extras']['post_upload_dir'];
46
+ $post_checksum = $post_struct['post_extras']['post_checksum'];
47
+ $post_featured_img = $post_struct['post_extras']['featured_img'];
48
+
49
+ $upload = wp_upload_dir();
50
+
51
+ // create dynamic url RegExp
52
+ $mwp_base_url = parse_url($post_upload_dir['url']);
53
+ $mwp_regexp_url = $mwp_base_url['host'] . $mwp_base_url['path'];
54
+ $rep = array(
55
+ '/',
56
+ '+',
57
+ '.',
58
+ ':',
59
+ '?'
60
+ );
61
+ $with = array(
62
+ '\/',
63
+ '\+',
64
+ '\.',
65
+ '\:',
66
+ '\?'
67
+ );
68
+ $mwp_regexp_url = str_replace($rep, $with, $mwp_regexp_url);
69
+
70
+ // rename all src ../wp-content/ with hostname/wp-content/
71
+ $mmb_dot_url = '..' . $mmb_base_url['path'];
72
+ $mmb_dot_url = str_replace($rep, $with, $mmb_dot_url);
73
+ $dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
74
+ if ($dot_match_count > 0) {
75
+ foreach ($dot_get_urls as $dot_url) {
76
+ $match_dot = '/' . str_replace($rep, $with, $dot_url[4]) . '/';
77
+ $replace_dot = 'http://' . $mmb_base_url['host'] . substr($dot_url[4], 2, strlen($dot_url[4]));
78
+ $post_data['post_content'] = preg_replace($match_dot, $replace_dot, $post_data['post_content']);
79
+
80
+ if ($dot_url[1] != '') {
81
+ $match_dot_a = '/' . str_replace($rep, $with, $dot_url[2]) . '/';
82
+ $replace_dot_a = 'http://' . $mmb_base_url['host'] . substr($dot_url[2], 2, strlen($dot_url[2]));
83
+ $post_data['post_content'] = preg_replace($match_dot_a, $replace_dot_a, $post_data['post_content']);
84
+ }
85
+ }
86
+ }
87
+
88
+
89
+
90
+ //to find all the images
91
+ $match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]+' . $mmb_regexp_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $get_urls, PREG_SET_ORDER);
92
+ if ($match_count > 0) {
93
+ $attachments = array();
94
+ $post_content = $post_data['post_content'];
95
+
96
+ foreach ($get_urls as $get_url_k => $get_url) {
97
+ // unset url in attachment array
98
+ foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
99
+ $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
100
+ if (preg_match($match_patt_url, $get_url[4])) {
101
+ unset($post_atta_img[$atta_url_k]);
102
+ }
103
+ }
104
+
105
+ if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
106
+ if ($get_url[1] != '') {
107
+ // change src url
108
+ $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
109
+
110
+ $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
111
+ $s_mmb_rp = $s_img_atta[0];
112
+ $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
113
+ // change attachment url
114
+ if (preg_match('/attachment_id/i', $get_url[2])) {
115
+ $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
116
+ $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
117
+ $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
118
+ }
119
+ }
120
+ continue;
121
+ }
122
+
123
+ $no_thumb = '';
124
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
125
+ $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
126
+ } else {
127
+ $no_thumb = $get_url[4];
128
+ }
129
+
130
+ if(isset($upload['error']) && !empty($upload['error'])){
131
+ return array('error' => $upload['error']);
132
+ }
133
+ $file_name = basename($no_thumb);
134
+ $tmp_file = download_url($no_thumb);
135
+
136
+ if(is_wp_error($tmp_file)){
137
+ return array('error' => $tmp_file->get_error_message());
138
+ }
139
+
140
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
141
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
142
+ $renamed = @rename($tmp_file, $attach_upload['path']);
143
+ if ($renamed === true) {
144
+ $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
145
+ $replace_pattern = $attach_upload['url'];
146
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
147
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
148
+ $match_pattern = '/' . str_replace($rep, $with, preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4])) . '/';
149
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
150
+ }
151
+
152
+ $attachment = array(
153
+ 'post_title' => $file_name,
154
+ 'post_content' => '',
155
+ 'post_type' => 'attachment',
156
+ //'post_parent' => $post_id,
157
+ 'post_mime_type' => 'image/' . $get_url[5],
158
+ 'guid' => $attach_upload['url']
159
+ );
160
+
161
+ // Save the data
162
+
163
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
164
+
165
+ $attachments[$attach_id] = 0;
166
+
167
+ // featured image
168
+ if ($post_featured_img != '') {
169
+ $feat_img_url = '';
170
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
171
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
172
+ } else {
173
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
174
+ }
175
+ $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
176
+ if (preg_match($m_feat_url, $get_url[4])) {
177
+ $post_featured_img = '';
178
+ $attachments[$attach_id] = $attach_id;
179
+ }
180
+ }
181
+
182
+ // set $get_urls value[6] - parent atta_id
183
+ foreach ($get_urls as $url_k => $url_v) {
184
+ if ($get_url_k != $url_k) {
185
+ $s_get_url = '';
186
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
187
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
188
+ } else {
189
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
190
+ }
191
+ $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
192
+ if (preg_match($m_patt_url, $get_url[4])) {
193
+ array_push($get_urls[$url_k], $attach_id);
194
+ }
195
+ }
196
+ }
197
+
198
+
199
+ $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
200
+ wp_update_attachment_metadata($attach_id, $some_data);
201
+
202
+
203
+ // changing href of a tag
204
+ if ($get_url[1] != '') {
205
+ $mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
206
+ if (preg_match('/attachment_id/i', $get_url[2])) {
207
+ $mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
208
+ $post_content = preg_replace($mmb_mp, $mmb_rp, $post_content);
209
+ }
210
+ }
211
+ } else {
212
+ @unlink($tmp_file);
213
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
214
+
215
+ }
216
+ @unlink($tmp_file);
217
+ }
218
+
219
+
220
+ $post_data['post_content'] = $post_content;
221
+
222
+ }
223
+ if (count($post_atta_img)) {
224
+ foreach ($post_atta_img as $img) {
225
+ $file_name = basename($img['src']);
226
+
227
+ if(isset($upload['error']) && !empty($upload['error'])){
228
+ return array('error' => $upload['error']);
229
+ }
230
+
231
+ $tmp_file = download_url($img['src']);
232
+ if(is_wp_error($tmp_file)){
233
+ return array('error' => $tmp_file->get_error_message());
234
+ }
235
+
236
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
237
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
238
+ $renamed = @rename($tmp_file, $attach_upload['path']);
239
+ if ($renamed === true) {
240
+ $atta_ext = end(explode('.', $file_name));
241
+
242
+ $attachment = array(
243
+ 'post_title' => $file_name,
244
+ 'post_content' => '',
245
+ 'post_type' => 'attachment',
246
+ //'post_parent' => $post_id,
247
+ 'post_mime_type' => 'image/' . $atta_ext,
248
+ 'guid' => $attach_upload['url']
249
+ );
250
+
251
+ // Save the data
252
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
253
+ wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
254
+ $attachments[$attach_id] = 0;
255
+
256
+ // featured image
257
+ if ($post_featured_img != '') {
258
+ $feat_img_url = '';
259
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
260
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
261
+ } else {
262
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
263
+ }
264
+ $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
265
+ if (preg_match($m_feat_url, $img['src'])) {
266
+ $post_featured_img = '';
267
+ $attachments[$attach_id] = $attach_id;
268
+ }
269
+ }
270
+
271
+ } else {
272
+ @unlink($tmp_file);
273
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
274
+ }
275
+ @unlink($tmp_file);
276
+ }
277
+ }
278
+
279
+ //Prepare post data and temporarily remove content filters before insert post
280
+ $user = $this->mmb_get_user_info( $args['username'] );
281
+ if($user && $user->ID){
282
+ $post_data['post_author'] = $user->ID;
283
+ }
284
+ //remove filter which can brake scripts or html
285
+ remove_filter('content_save_pre', 'wp_filter_post_kses');
286
+
287
+ //check for edit post
288
+ $post_result = 0;
289
+ if(isset($post_data['mwp_post_edit']) && $post_data['mwp_post_edit']){
290
+
291
+
292
+ if($post_data['mwp_match_by'] == 'title'){
293
+ $match_by = "post_title = '".$post_data['post_title']."'";
294
+ } else {
295
+ $match_by = "post_name = '".$post_data['post_name']."'";
296
+ }
297
+
298
+ $query = "SELECT ID FROM $wpdb->posts WHERE $match_by AND post_status NOT IN('inherit','auto-draft','draft') LIMIT 1";
299
+
300
+ $post_result = $wpdb->get_var($query);
301
+
302
+ }
303
+
304
+
305
+ if($post_result){
306
+ //update existing post
307
+ $post_data['ID'] = $post_result;
308
+ $post_id = wp_update_post($post_data);
309
+
310
+ //check for previous attachments
311
+ $atta_allimages =& get_children('post_type=attachment&post_parent=' . $post_id);
312
+ if (!empty($atta_allimages)) {
313
+ foreach ($atta_allimages as $image) {
314
+ wp_delete_attachment($image->ID);
315
+ }
316
+ }
317
+
318
+ } else {
319
+ if($post_data['mwp_post_edit'] && $post_data['mwp_force_publish']){
320
+ $post_id = wp_insert_post($post_data);
321
+ } elseif($post_data['mwp_post_edit'] && !$post_data['mwp_force_publish']) {
322
+ return array('error' => "Post not found.");
323
+ } else {
324
+ $post_id = wp_insert_post($post_data);
325
+ }
326
+
327
+ }
328
+
329
+ if (count($attachments)) {
330
+ foreach ($attachments as $atta_id => $featured_id) {
331
+ $result = wp_update_post(array(
332
+ 'ID' => $atta_id,
333
+ 'post_parent' => $post_id
334
+ ));
335
+ if ($featured_id > 0) {
336
+ $new_custom['_thumbnail_id'] = array(
337
+ $featured_id
338
+ );
339
+ }
340
+ }
341
+ }
342
+
343
+ // featured image
344
+ if ($post_featured_img != '') {
345
+ $file_name = basename($post_featured_img);
346
+ if(isset($upload['error']) && !empty($upload['error'])){
347
+ return array('error' => $upload['error']);
348
+ }
349
+ $tmp_file = download_url($post_featured_img);
350
+ if(is_wp_error($tmp_file)){
351
+ return array('error' => $tmp_file->get_error_message());
352
+ }
353
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
354
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
355
+ $renamed = @rename($tmp_file, $attach_upload['path']);
356
+ if ($renamed === true) {
357
+ $atta_ext = end(explode('.', $file_name));
358
+
359
+ $attachment = array(
360
+ 'post_title' => $file_name,
361
+ 'post_content' => '',
362
+ 'post_type' => 'attachment',
363
+ 'post_parent' => $post_id,
364
+ 'post_mime_type' => 'image/' . $atta_ext,
365
+ 'guid' => $attach_upload['url']
366
+ );
367
+
368
+ // Save the data
369
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
370
+ wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attach_upload['path']));
371
+ $new_custom['_thumbnail_id'] = array(
372
+ $attach_id
373
+ );
374
+ } else {
375
+ @unlink($tmp_file);
376
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
377
+ }
378
+ @unlink($tmp_file);
379
+ }
380
+
381
+ if ($post_id && is_array($post_categories)) {
382
+ //insert categories
383
+
384
+ $cat_ids = wp_create_categories($post_categories, $post_id);
385
+ }
386
+
387
+
388
+ //get current custom fields
389
+ $cur_custom = get_post_custom($post_id);
390
+ //check which values doesnot exists in new custom fields
391
+ $diff_values = array_diff_key($cur_custom, $new_custom);
392
+
393
+ if (is_array($diff_values))
394
+ foreach ($diff_values as $meta_key => $value) {
395
+ delete_post_meta($post_id, $meta_key);
396
+ }
397
+ //insert new post meta
398
+ foreach ($new_custom as $meta_key => $value) {
399
+ if (strpos($meta_key, '_mmb') === 0 || strpos($meta_key, '_edit') === 0) {
400
+ continue;
401
+ } else {
402
+ update_post_meta($post_id, $meta_key, $value[0]);
403
+ }
404
+ }
405
+ return $post_id;
406
+ }
407
+
408
+
409
+ function change_status($args)
410
+ {
411
+
412
+ global $wpdb;
413
+ $post_id = $args['post_id'];
414
+ $status = $args['status'];
415
+ $success = false;
416
+
417
+ if(in_array($status, array('draft', 'publish', 'trash'))){
418
+ $sql = "update ".$wpdb->prefix."posts set post_status = '$status' where ID = '$post_id'";
419
+ $success = $wpdb->query($sql);
420
+ }
421
+
422
+ return $success;
423
+ }
424
+
425
+ function get_posts($args){
426
+ global $wpdb;
427
+
428
+ $where='';
429
+
430
+ extract($args);
431
+
432
+ if(!empty($filter_posts))
433
+ {
434
+ $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_posts)."%'";
435
+ }
436
+
437
+ if(!empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
438
+ {
439
+ $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_posts_date_from)."' AND '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
440
+ }
441
+ else if(!empty($mwp_get_posts_date_from) && empty($mwp_get_posts_date_to))
442
+ {
443
+ $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_posts_date_from)."'";
444
+ }
445
+ else if(empty($mwp_get_posts_date_from) && !empty($mwp_get_posts_date_to))
446
+ {
447
+ $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_posts_date_to)."'";
448
+ }
449
+ $post_array=array();
450
+ $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
451
+ foreach ($args as $checkbox => $checkbox_val)
452
+ {
453
+ if($checkbox_val=="on") {
454
+ $post_array[]="'".str_replace("mwp_get_posts_","",$checkbox)."'";
455
+ }
456
+ }
457
+ if(!empty($post_array))
458
+ {
459
+ $where.=" AND post_status IN (".implode(",",$post_array).")";
460
+ }
461
+
462
+ $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='post' ".$where." ORDER BY post_date DESC";
463
+
464
+ $total = array();
465
+ $user_info = $this->getUsersIDs();
466
+ $post_cats=$this->getPostCats();
467
+ $post_tags=$this->getPostCats('post_tag');
468
+ $posts_total = $wpdb->get_results("SELECT count(*) as total_posts FROM ".$sql_query);
469
+ $total['total_num']=$posts_total[0]->total_posts;
470
+
471
+ $posts = array();
472
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query." LIMIT 500");
473
+
474
+ foreach ( $posts_info as $post_info )
475
+ {
476
+
477
+ $cats=array();
478
+ foreach($post_cats[$post_info->ID] as $cat_array => $cat_array_val)
479
+ {
480
+ $cats[] = array('name' => $cat_array_val);
481
+ }
482
+
483
+ $tags=array();
484
+ foreach($post_tags[$post_info->ID] as $tag_array => $tag_array_val)
485
+ {
486
+ $tags[] = array('name' => $tag_array_val);
487
+ }
488
+
489
+ $posts[]=array(
490
+ 'post_id'=>$post_info->ID,
491
+ 'post_title'=>$post_info->post_title,
492
+ 'post_name'=>$post_info->post_name,
493
+ 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
494
+ 'post_date'=>$post_info->post_date,
495
+ 'post_modified'=>$post_info->post_modified,
496
+ 'post_status'=>$post_info->post_status,
497
+ 'post_type'=>$post_info->post_type,
498
+ 'guid'=>$post_info->guid,
499
+ 'post_password'=>$post_info->post_password,
500
+ 'ping_status'=>$post_info->ping_status,
501
+ 'comment_status'=>$post_info->comment_status,
502
+ 'comment_count'=>$post_info->comment_count,
503
+ 'cats'=>$cats,
504
+ 'tags'=>$tags,
505
+
506
+ );
507
+ }
508
+
509
+ return array('posts' => $posts, 'total' => $total);
510
+ }
511
+
512
+ function delete_post($args){
513
+ global $wpdb;
514
+ if(!empty($args['post_id']) && !empty($args['action']))
515
+ {
516
+ if($args['action']=='delete')
517
+ {
518
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
519
+ }
520
+ else if($args['action']=='delete_perm'){
521
+ $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
522
+ }
523
+ else if($args['action']=='delete_restore'){
524
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
525
+ }
526
+ $wpdb->get_results($delete_query);
527
+
528
+ return 'Post deleted.';
529
+ }
530
+ else
531
+ {
532
+ return 'No ID...';
533
+ }
534
+ }
535
+
536
+ function delete_posts($args){
537
+ global $wpdb;
538
+ extract($args);
539
+ if($deleteaction=='delete'){
540
+ $delete_query_intro = "DELETE FROM $wpdb->posts WHERE ID = ";
541
+ }elseif($deleteaction=='trash'){
542
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ";
543
+ }elseif($deleteaction=='draft'){
544
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = ";
545
+ }elseif($deleteaction=='publish'){
546
+ $delete_query_intro = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ";
547
+ }
548
+ foreach($args as $key=>$val){
549
+
550
+ if(!empty($val) && is_numeric($val))
551
+ {
552
+ $delete_query = $delete_query_intro.$val;
553
+
554
+ $wpdb->query($delete_query);
555
+ }
556
+ }
557
+ return "Post deleted";
558
+
559
+ }
560
+
561
+ function get_pages($args){
562
+ global $wpdb;
563
+
564
+ $where='';
565
+ extract($args);
566
+
567
+ if(!empty($filter_pages))
568
+ {
569
+ $where.=" AND post_title LIKE '%".mysql_real_escape_string($filter_pages)."%'";
570
+ }
571
+ if(!empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
572
+ {
573
+ $where.=" AND post_date BETWEEN '".mysql_real_escape_string($mwp_get_pages_date_from)."' AND '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
574
+ }
575
+ else if(!empty($mwp_get_pages_date_from) && empty($mwp_get_pages_date_to))
576
+ {
577
+ $where.=" AND post_date >= '".mysql_real_escape_string($mwp_get_pages_date_from)."'";
578
+ }
579
+ else if(empty($mwp_get_pages_date_from) && !empty($mwp_get_pages_date_to))
580
+ {
581
+ $where.=" AND post_date <= '".mysql_real_escape_string($mwp_get_pages_date_to)."'";
582
+ }
583
+
584
+ $post_array=array();
585
+ $post_statuses = array('publish', 'pending', 'private', 'future', 'draft', 'trash');
586
+ foreach ($args as $checkbox => $checkbox_val)
587
+ {
588
+ if($checkbox_val=="on") {
589
+ $post_array[]="'".str_replace("mwp_get_pages_","",$checkbox)."'";
590
+ }
591
+ }
592
+ if(!empty($post_array))
593
+ {
594
+ $where.=" AND post_status IN (".implode(",",$post_array).")";
595
+ }
596
+
597
+ $sql_query = "$wpdb->posts WHERE post_status!='auto-draft' AND post_status!='inherit' AND post_type='page' ".$where.' ORDER BY post_date DESC';
598
+
599
+ $total = array();
600
+ $user_info = $this->getUsersIDs();
601
+ $posts_total = $wpdb->get_results("SELECT count(*) as total_posts FROM ".$sql_query);
602
+ $total['total_num']=$posts_total[0]->total_posts;
603
+
604
+ $posts = array();
605
+ $posts_info = $wpdb->get_results("SELECT * FROM ".$sql_query." LIMIT 500");
606
+
607
+ foreach ( $posts_info as $post_info )
608
+ {
609
+
610
+ $posts[]=array(
611
+ 'post_id'=>$post_info->ID,
612
+ 'post_title'=>$post_info->post_title,
613
+ 'post_name'=>$post_info->post_name,
614
+ 'post_author'=>array('author_id'=>$post_info->post_author, 'author_name'=>$user_info[$post_info->post_author]),
615
+ 'post_date'=>$post_info->post_date,
616
+ 'post_modified'=>$post_info->post_modified,
617
+ 'post_status'=>$post_info->post_status,
618
+ 'post_type'=>$post_info->post_type,
619
+ 'guid'=>$post_info->guid,
620
+ 'post_password'=>$post_info->post_password,
621
+ 'ping_status'=>$post_info->ping_status,
622
+ 'comment_status'=>$post_info->comment_status,
623
+ 'comment_count'=>$post_info->comment_count
624
+
625
+ );
626
+ }
627
+
628
+ return array('posts' => $posts, 'total' => $total);
629
+ }
630
+
631
+ function delete_page($args){
632
+ global $wpdb;
633
+ if(!empty($args['post_id']) && !empty($args['action']))
634
+ {
635
+ if($args['action']=='delete')
636
+ {
637
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID = ".$args['post_id'];
638
+ }
639
+ else if($args['action']=='delete_perm'){
640
+ $delete_query = "DELETE FROM $wpdb->posts WHERE ID = ".$args['post_id'];
641
+ }
642
+ else if($args['action']=='delete_restore'){
643
+ $delete_query = "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = ".$args['post_id'];
644
+ }
645
+ $wpdb->get_results($delete_query);
646
+
647
+ return 'Page deleted.';
648
+ }
649
+ else
650
+ {
651
+ return 'No ID...';
652
+ }
653
+ }
654
+
655
+ function getPostCats($taxonomy = 'category')
656
+ {
657
+ global $wpdb;
658
+
659
+ $cats = $wpdb->get_results("SELECT p.ID AS post_id, $wpdb->terms.name
660
+ FROM $wpdb->posts AS p
661
+ INNER JOIN $wpdb->term_relationships ON ( p.ID = $wpdb->term_relationships.object_id )
662
+ INNER JOIN $wpdb->term_taxonomy ON ( $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
663
+ AND $wpdb->term_taxonomy.taxonomy = '".$taxonomy."' )
664
+ INNER JOIN $wpdb->terms ON ( $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id )");
665
+
666
+ foreach ( $cats as $post_val )
667
+ {
668
+
669
+ $post_cats[$post_val->post_id][] = $post_val->name;
670
+ }
671
+
672
+ return $post_cats;
673
+ }
674
+
675
+ function getUsersIDs()
676
+ {
677
+ global $wpdb;
678
+ $users_authors=array();
679
+ $users = $wpdb->get_results("SELECT ID as user_id, display_name FROM $wpdb->users WHERE user_status=0");
680
+
681
+ foreach ( $users as $user_key=>$user_val )
682
+ {
683
+ $users_authors[$user_val->user_id] = $user_val->display_name;
684
+ }
685
+
686
+ return $users_authors;
687
+ }
688
+ }
689
  ?>
readme.txt CHANGED
@@ -1,246 +1,251 @@
1
- === ManageWP Worker ===
2
- Contributors: freediver
3
- Donate link: https://www.networkforgood.org/donation/MakeDonation.aspx?ORGID2=520781390
4
- Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multsite, notification, performance, s3, security, seo, stats, tracking, managewp
5
- Requires at least: 3.0
6
- Tested up to: 3.4
7
- Stable tag: trunk
8
-
9
- ManageWP Worker plugin allows you to remotely manage your WordPress sites from one dashboard.
10
-
11
- == Description ==
12
-
13
- [ManageWP](http://managewp.com/ "Manage Multiple Blogs") is a revolutionary plugin that helps users manage multiple WordPress blogs from one dashboard.
14
-
15
- Main features:
16
-
17
- * Secure and fast solution for managing your WordPress sites
18
- * One click upgrades for WordPress, plugin and themes across all your sites
19
- * Schedule automatic backups of your websites (Amazon S3 and Dropbox supported)
20
- * One click to access WP admin of any site
21
- * Install WordPress, clone or migrate a website to another domain
22
- * Bulk install themes and plugins to multiple sites at once
23
- * Add sub-users (writers, staff..) to your account
24
- * Bulk publish posts to multiple sites at once
25
- * SEO Statistics, track your keyword rankings
26
- * Uptime monitoring
27
- * Much, much more...
28
-
29
- Check out the [ManageWP Tour video](http://vimeo.com/22099014).
30
-
31
- http://vimeo.com/22099014
32
-
33
- Check out [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs").
34
-
35
- == Changelog ==
36
-
37
- = 3.9.19 =
38
- * New: Improved mechanism for refreshing website stats. You should have fresh information every 4 hours without refreshing now
39
- * Fix: Categories now showing properly in Manage posts
40
- * Fix: Website stats now ignore uptime monitoring pings
41
-
42
- = 3.9.18 =
43
- * New: Pagelines themes added to the list of partners
44
- * New: Comprehensive website performance scan tool
45
- * New: You can now bulk edit posts/pages (updating that contact info will become piece of cake)
46
- * New: Upload and save your premium plugins/themes in your personal repository for quick installation
47
- * New: Run code snippets now get a repository. Save your snippets and share them with other users
48
- * New: SEO reports can now be sorted. Export as CSV and PDF reports.
49
- * New: Manage Blogroll links
50
- * New: Clean post revisions now has an option to save last x revisions when cleaning
51
- * New: Bulk delete na posts/pages/links
52
- * Fix: Amazon S3 backups failing
53
-
54
- = 3.9.17 =
55
- * New: Add your favorite sites to the Favorites bar (just drag&drop them to the small heart on the top)
56
- * New: Entirely new website menu loaded with features and tools
57
- * New: Manage Posts and Pages across all sites in a more efficient way
58
- * New: Support for all WPMU.org premium plugin updates
59
- * New: Complete Dropbox integration through Oauth which allows us to restore/delete Dropbox backups directly
60
- * New: We have the user guide as PDF now. [Download] (http://managewp.com/files/ManageWP_User_Guide.zip)
61
-
62
-
63
- = 3.9.16 =
64
- * New: Option to "Run now" backup tasks
65
- * New: Traffic alerts functionality
66
- * New: Support for Genesis premium theme updates
67
- * Fix: In some circutmsances .htaccess was not correctly zipped in the backup archive
68
-
69
- = 3.9.15 =
70
- * New: Full range of SEO Statistics now trackable for your websites (Google Page Rank and Page Speed, Backlinks and 20+ more)
71
- * New: Google keyword rank tracking with history
72
- * New: Uptime monitoring (5 min interval with email/SMS notification)
73
- * New: Insights into server PHP error logs right in your dashboard
74
- * New: Remote maintenance mode for your websites
75
- * Fix: A bug when a completed backup was reported as failed
76
-
77
- = 3.9.14 =
78
- * Two factor authentication
79
- * Run code tool
80
- * Quick access to security check and broken link tools
81
- * More accurate pageview statistics
82
- * You can now opt to completely hide the Worker plugin from the list of plugins (part of Worker branding features)
83
- * We improved the backups for folks running Windows servers
84
- * Amazon S3 directory name now "ManageWP" by default
85
- * Read more on ManageWP.com http://managewp.com/update-two-factor-authentication-run-code-tool-sucuri-security-check-more-accurate-pageview-statistics
86
-
87
- = 3.9.13 =
88
- * Added bucket location for Amazon S3 backups
89
- * Better backup feature for larger sites
90
- * Added Disable compression to further help with larger sites
91
- * Backing up wp-admin, wp-includes and wp-content by default now, other folders can be included manually
92
-
93
- = 3.9.12 =
94
- * Minor bug fixes
95
- * Backup, clone, favorites functionality improved
96
-
97
- = 3.9.10 =
98
- * Supporting updates for more premium plugins/themes
99
- * Backup notifications (users can now get notices when the backup succeeds or fails)
100
- * Support for WordPress 3.3
101
- * Worker Branding (useful for web agencies, add your own Name/Description)
102
- * Manage Groups screen
103
- * Specify wp-admin path if your site uses a custom one
104
- * Amazon S3 backups support for mixed case bucket names
105
- * Bulk Add Links has additional options
106
- * Better Multisite support
107
- * Option to set the number of items for Google Analytics
108
- * ManageWP backup folder changed to wp-content/managewp/backups
109
-
110
- = 3.9.9 =
111
- * New widget on the dashboard - Backup status
112
- * New screen for managing plugins and themes (activate, deactivate, delete, add to favorites, install) across all sites
113
- * New screen for managing users (change role or password, delete user) across all sites
114
- * Option to overwrite old plugins and themes during bulk installation
115
- * Your website admin now loads faster in ManageWP
116
- * Added API for premium theme and plugin updates
117
-
118
- = 3.9.8 =
119
- * Conversion goals integration
120
- * Update notifications
121
- * Enhanced security for your account
122
- * Better backups
123
- * Better update interface
124
- * [Full changelog](http://managewp.com/update-goals-and-adsense-analytics-integration-update-notifications-login-by-ip-better-backups "Full changelog")
125
-
126
- = 3.9.7 =
127
- * Fixed problem with cron schedules
128
-
129
- = 3.9.6 =
130
- * Improved dashboard performance
131
- * Fixed bug with W3TC, we hope it is fully comptabile now
132
- * Improved backup feature
133
- * Various other fixes and improvements
134
-
135
- = 3.9.5 =
136
- * Now supporting scheduled backups to Amazon S3 and Dropbox
137
- * Revamped cloning procedure
138
- * You can now have sites in different colors
139
- * W3 Total Cache comptability improved
140
-
141
- = 3.9.3 =
142
- * Included support for WordPress 3.2 partial updates
143
-
144
- = 3.9.2 =
145
- * Fixed problem with full backups
146
- * Fixed problem with wordpress dev version upgrades
147
-
148
- = 3.9.1 =
149
- * Support for sub-users (limited access users)
150
- * Bulk add user
151
- * 'Select all' feature for bulk posting
152
- * Featured image support for bulk posting
153
- * Reload button on the dashboard (on the top of the Right now widget) will now refresh information about available updates
154
- * Fixed a problem with the import tool
155
- * Fixed a problem when remote dashboard would not work for some servers
156
-
157
- = 3.9.0 =
158
- * New feature: Up to 50% faster dashboard loading
159
- * New feature: You can now ignore WordPress/plugin/theme updates
160
- * New feature: Setting 'Show favicon' for websites in the dashboad
161
- * New feature: Full backups now include WordPress and other folders in the root of the site
162
- * Fixed: Bug with W3 TotalCache object cache causing weird behaviour in the dashboard
163
- * Fixed: All groups now show when adding a site
164
-
165
- = 3.8.8 =
166
- * New feature: Bulk add links to blogroll
167
- * New feature: Manual backups to email address
168
- * New feature: Backup requirements check (under �Manage Backups�)
169
- * New feature: Popup menu for groups allowing to show dashboard for that group only
170
- * New feature: Favorite list for plugins and themes for later quick installation to multiple blogs
171
- * New feature: Invite friends
172
- * Fixed: problem with backups and write permissions when upload dir was wrongly set
173
- * Fixed: problem adding sites where WordPress is installed in a folder
174
- * Fixed: 408 error message problem when adding site
175
- * Fixed: site time out problems when adding site
176
- * Fixed: problems with some WP plugins (WP Sentinel)
177
- * Fixed: problems with upgrade notifications
178
-
179
- = 3.8.7 =
180
- * Fixed 408 error when adding sites
181
- * Added support for IDN domains
182
- * Fixed bug with WordPress updates
183
- * Added comment moderation to the dashboard
184
- * Added quick links for sites (menu appears on hover)
185
-
186
-
187
- = 3.8.6 =
188
- * Added seach websites feature
189
- * Enhanced dashboard actions (spam comments, post revisions, table overhead)
190
- * Added developer [API] (http://managewp.com/api "ManageWP API")
191
- * Improved Migrate/Clone site feature
192
-
193
- = 3.8.4 =
194
- * Fixed remote dashboard problems for sites with redirects
195
- * Fixed IE7 issues in the dashboard
196
-
197
- = 3.8.3 =
198
- * Fixed problem with capabilities
199
-
200
- = 3.8.2 =
201
- * New interface
202
- * SSL security protocol
203
- * No passwords required
204
- * Improved clone/backup
205
-
206
-
207
- = 3.6.3 =
208
- * Initial public release
209
-
210
- == Installation ==
211
-
212
- 1. Upload the plugin folder to your /wp-content/plugins/ folder
213
- 2. Go to the Plugins page and activate ManageWP Worker
214
- 3. Visit [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs"), sign up and add your site
215
-
216
- Alternately
217
-
218
- 1. Visit [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs"), sign up and add your site
219
- 2. ManageWP will warn you the worker plugin is not installed and offer a link for quick installation
220
-
221
- == Screenshots ==
222
-
223
- 1. ManageWP dashboard with available upgrades, site statistics and management functions
224
-
225
-
226
-
227
- == License ==
228
-
229
- This file is part of ManageWP Worker.
230
-
231
- ManageWP Worker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
232
-
233
- ManageWP Worker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
234
-
235
- You should have received a copy of the GNU General Public License along with ManageWP Worker. If not, see <http://www.gnu.org/licenses/>.
236
-
237
-
238
- == Frequently Asked Questions ==
239
-
240
- = I have problems adding my site =
241
-
242
- Make sure you use the latest version of the worker plugin on the site you are trying to add. If you do, sometimes deactivating and activating it again will help. If you still have problems, [contact us](http://managewp.com/contact "ManageWP Contact").
243
-
244
- = I have problems installing new plugins or upgrading WordPress through ManageWP =
245
-
 
 
 
 
 
246
  ManageWP Worker relies on properly set file permissions on your server. See the [user guide](http://managewp.com/user-guide#ftp "ManageWP user guide") for more tips.
1
+ === ManageWP Worker ===
2
+ Contributors: freediver
3
+ Donate link: https://www.networkforgood.org/donation/MakeDonation.aspx?ORGID2=520781390
4
+ Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multsite, notification, performance, s3, security, seo, stats, tracking, managewp
5
+ Requires at least: 3.0
6
+ Tested up to: 3.4.1
7
+ Stable tag: trunk
8
+
9
+ ManageWP Worker plugin allows you to remotely manage your WordPress sites from one dashboard.
10
+
11
+ == Description ==
12
+
13
+ [ManageWP](http://managewp.com/ "Manage Multiple Blogs") is a revolutionary plugin that helps users manage multiple WordPress blogs from one dashboard.
14
+
15
+ Main features:
16
+
17
+ * Secure and fast solution for managing your WordPress sites
18
+ * One click upgrades for WordPress, plugin and themes across all your sites
19
+ * Schedule automatic backups of your websites (Amazon S3 and Dropbox supported)
20
+ * One click to access WP admin of any site
21
+ * Install WordPress, clone or migrate a website to another domain
22
+ * Bulk install themes and plugins to multiple sites at once
23
+ * Add sub-users (writers, staff..) to your account
24
+ * Bulk publish posts to multiple sites at once
25
+ * SEO Statistics, track your keyword rankings
26
+ * Uptime monitoring
27
+ * Much, much more...
28
+
29
+ Check out the [ManageWP Tour video](http://vimeo.com/22099014).
30
+
31
+ http://vimeo.com/22099014
32
+
33
+ Check out [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs").
34
+
35
+ == Changelog ==
36
+
37
+ = 3.9.20 =
38
+ * New: ManageWP iOS app compatibility
39
+ * New: Perform security and performance test as you add websites
40
+ * New: New comment handling screen
41
+
42
+ = 3.9.19 =
43
+ * New: Improved mechanism for refreshing website stats. You should have fresh information every 4 hours without refreshing now
44
+ * Fix: Categories now showing properly in Manage posts
45
+ * Fix: Website stats now ignore uptime monitoring pings
46
+
47
+ = 3.9.18 =
48
+ * New: Pagelines themes added to the list of partners
49
+ * New: Comprehensive website performance scan tool
50
+ * New: You can now bulk edit posts/pages (updating that contact info will become piece of cake)
51
+ * New: Upload and save your premium plugins/themes in your personal repository for quick installation
52
+ * New: Run code snippets now get a repository. Save your snippets and share them with other users
53
+ * New: SEO reports can now be sorted. Export as CSV and PDF reports.
54
+ * New: Manage Blogroll links
55
+ * New: Clean post revisions now has an option to save last x revisions when cleaning
56
+ * New: Bulk delete na posts/pages/links
57
+ * Fix: Amazon S3 backups failing
58
+
59
+ = 3.9.17 =
60
+ * New: Add your favorite sites to the Favorites bar (just drag&drop them to the small heart on the top)
61
+ * New: Entirely new website menu loaded with features and tools
62
+ * New: Manage Posts and Pages across all sites in a more efficient way
63
+ * New: Support for all WPMU.org premium plugin updates
64
+ * New: Complete Dropbox integration through Oauth which allows us to restore/delete Dropbox backups directly
65
+ * New: We have the user guide as PDF now. [Download] (http://managewp.com/files/ManageWP_User_Guide.zip)
66
+
67
+
68
+ = 3.9.16 =
69
+ * New: Option to "Run now" backup tasks
70
+ * New: Traffic alerts functionality
71
+ * New: Support for Genesis premium theme updates
72
+ * Fix: In some circutmsances .htaccess was not correctly zipped in the backup archive
73
+
74
+ = 3.9.15 =
75
+ * New: Full range of SEO Statistics now trackable for your websites (Google Page Rank and Page Speed, Backlinks and 20+ more)
76
+ * New: Google keyword rank tracking with history
77
+ * New: Uptime monitoring (5 min interval with email/SMS notification)
78
+ * New: Insights into server PHP error logs right in your dashboard
79
+ * New: Remote maintenance mode for your websites
80
+ * Fix: A bug when a completed backup was reported as failed
81
+
82
+ = 3.9.14 =
83
+ * Two factor authentication
84
+ * Run code tool
85
+ * Quick access to security check and broken link tools
86
+ * More accurate pageview statistics
87
+ * You can now opt to completely hide the Worker plugin from the list of plugins (part of Worker branding features)
88
+ * We improved the backups for folks running Windows servers
89
+ * Amazon S3 directory name now "ManageWP" by default
90
+ * Read more on ManageWP.com http://managewp.com/update-two-factor-authentication-run-code-tool-sucuri-security-check-more-accurate-pageview-statistics
91
+
92
+ = 3.9.13 =
93
+ * Added bucket location for Amazon S3 backups
94
+ * Better backup feature for larger sites
95
+ * Added Disable compression to further help with larger sites
96
+ * Backing up wp-admin, wp-includes and wp-content by default now, other folders can be included manually
97
+
98
+ = 3.9.12 =
99
+ * Minor bug fixes
100
+ * Backup, clone, favorites functionality improved
101
+
102
+ = 3.9.10 =
103
+ * Supporting updates for more premium plugins/themes
104
+ * Backup notifications (users can now get notices when the backup succeeds or fails)
105
+ * Support for WordPress 3.3
106
+ * Worker Branding (useful for web agencies, add your own Name/Description)
107
+ * Manage Groups screen
108
+ * Specify wp-admin path if your site uses a custom one
109
+ * Amazon S3 backups support for mixed case bucket names
110
+ * Bulk Add Links has additional options
111
+ * Better Multisite support
112
+ * Option to set the number of items for Google Analytics
113
+ * ManageWP backup folder changed to wp-content/managewp/backups
114
+
115
+ = 3.9.9 =
116
+ * New widget on the dashboard - Backup status
117
+ * New screen for managing plugins and themes (activate, deactivate, delete, add to favorites, install) across all sites
118
+ * New screen for managing users (change role or password, delete user) across all sites
119
+ * Option to overwrite old plugins and themes during bulk installation
120
+ * Your website admin now loads faster in ManageWP
121
+ * Added API for premium theme and plugin updates
122
+
123
+ = 3.9.8 =
124
+ * Conversion goals integration
125
+ * Update notifications
126
+ * Enhanced security for your account
127
+ * Better backups
128
+ * Better update interface
129
+ * [Full changelog](http://managewp.com/update-goals-and-adsense-analytics-integration-update-notifications-login-by-ip-better-backups "Full changelog")
130
+
131
+ = 3.9.7 =
132
+ * Fixed problem with cron schedules
133
+
134
+ = 3.9.6 =
135
+ * Improved dashboard performance
136
+ * Fixed bug with W3TC, we hope it is fully comptabile now
137
+ * Improved backup feature
138
+ * Various other fixes and improvements
139
+
140
+ = 3.9.5 =
141
+ * Now supporting scheduled backups to Amazon S3 and Dropbox
142
+ * Revamped cloning procedure
143
+ * You can now have sites in different colors
144
+ * W3 Total Cache comptability improved
145
+
146
+ = 3.9.3 =
147
+ * Included support for WordPress 3.2 partial updates
148
+
149
+ = 3.9.2 =
150
+ * Fixed problem with full backups
151
+ * Fixed problem with wordpress dev version upgrades
152
+
153
+ = 3.9.1 =
154
+ * Support for sub-users (limited access users)
155
+ * Bulk add user
156
+ * 'Select all' feature for bulk posting
157
+ * Featured image support for bulk posting
158
+ * Reload button on the dashboard (on the top of the Right now widget) will now refresh information about available updates
159
+ * Fixed a problem with the import tool
160
+ * Fixed a problem when remote dashboard would not work for some servers
161
+
162
+ = 3.9.0 =
163
+ * New feature: Up to 50% faster dashboard loading
164
+ * New feature: You can now ignore WordPress/plugin/theme updates
165
+ * New feature: Setting 'Show favicon' for websites in the dashboad
166
+ * New feature: Full backups now include WordPress and other folders in the root of the site
167
+ * Fixed: Bug with W3 TotalCache object cache causing weird behaviour in the dashboard
168
+ * Fixed: All groups now show when adding a site
169
+
170
+ = 3.8.8 =
171
+ * New feature: Bulk add links to blogroll
172
+ * New feature: Manual backups to email address
173
+ * New feature: Backup requirements check (under �Manage Backups�)
174
+ * New feature: Popup menu for groups allowing to show dashboard for that group only
175
+ * New feature: Favorite list for plugins and themes for later quick installation to multiple blogs
176
+ * New feature: Invite friends
177
+ * Fixed: problem with backups and write permissions when upload dir was wrongly set
178
+ * Fixed: problem adding sites where WordPress is installed in a folder
179
+ * Fixed: 408 error message problem when adding site
180
+ * Fixed: site time out problems when adding site
181
+ * Fixed: problems with some WP plugins (WP Sentinel)
182
+ * Fixed: problems with upgrade notifications
183
+
184
+ = 3.8.7 =
185
+ * Fixed 408 error when adding sites
186
+ * Added support for IDN domains
187
+ * Fixed bug with WordPress updates
188
+ * Added comment moderation to the dashboard
189
+ * Added quick links for sites (menu appears on hover)
190
+
191
+
192
+ = 3.8.6 =
193
+ * Added seach websites feature
194
+ * Enhanced dashboard actions (spam comments, post revisions, table overhead)
195
+ * Added developer [API] (http://managewp.com/api "ManageWP API")
196
+ * Improved Migrate/Clone site feature
197
+
198
+ = 3.8.4 =
199
+ * Fixed remote dashboard problems for sites with redirects
200
+ * Fixed IE7 issues in the dashboard
201
+
202
+ = 3.8.3 =
203
+ * Fixed problem with capabilities
204
+
205
+ = 3.8.2 =
206
+ * New interface
207
+ * SSL security protocol
208
+ * No passwords required
209
+ * Improved clone/backup
210
+
211
+
212
+ = 3.6.3 =
213
+ * Initial public release
214
+
215
+ == Installation ==
216
+
217
+ 1. Upload the plugin folder to your /wp-content/plugins/ folder
218
+ 2. Go to the Plugins page and activate ManageWP Worker
219
+ 3. Visit [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs"), sign up and add your site
220
+
221
+ Alternately
222
+
223
+ 1. Visit [ManageWP.com](http://managewp.com/ "Manage Multiple Blogs"), sign up and add your site
224
+ 2. ManageWP will warn you the worker plugin is not installed and offer a link for quick installation
225
+
226
+ == Screenshots ==
227
+
228
+ 1. ManageWP dashboard with available upgrades, site statistics and management functions
229
+
230
+
231
+
232
+ == License ==
233
+
234
+ This file is part of ManageWP Worker.
235
+
236
+ ManageWP Worker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
237
+
238
+ ManageWP Worker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
239
+
240
+ You should have received a copy of the GNU General Public License along with ManageWP Worker. If not, see <http://www.gnu.org/licenses/>.
241
+
242
+
243
+ == Frequently Asked Questions ==
244
+
245
+ = I have problems adding my site =
246
+
247
+ Make sure you use the latest version of the worker plugin on the site you are trying to add. If you do, sometimes deactivating and activating it again will help. If you still have problems, [contact us](http://managewp.com/contact "ManageWP Contact").
248
+
249
+ = I have problems installing new plugins or upgrading WordPress through ManageWP =
250
+
251
  ManageWP Worker relies on properly set file permissions on your server. See the [user guide](http://managewp.com/user-guide#ftp "ManageWP user guide") for more tips.
stats.class.php CHANGED
@@ -1,784 +1,801 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * stats.class.php
5
- *
6
- * Get Site Stats
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "stats.class.php"):
13
- exit;
14
- endif;
15
-
16
- class MMB_Stats extends MMB_Core
17
- {
18
- function __construct()
19
- {
20
- parent::__construct();
21
- }
22
-
23
- /*************************************************************
24
- * FACADE functions
25
- * (functions to be called after a remote call from Master)
26
- **************************************************************/
27
-
28
- function get_core_update($stats, $options = array())
29
- {
30
- global $wp_version;
31
-
32
- if (isset($options['core']) && $options['core']) {
33
- $core = $this->mmb_get_transient('update_core');
34
- if (isset($core->updates) && !empty($core->updates)) {
35
- $current_transient = $core->updates[0];
36
- if ($current_transient->response == "development" || version_compare($wp_version, $current_transient->current, '<')) {
37
- $current_transient->current_version = $wp_version;
38
- $stats['core_updates'] = $current_transient;
39
- } else
40
- $stats['core_updates'] = false;
41
- } else
42
- $stats['core_updates'] = false;
43
- }
44
-
45
- return $stats;
46
- }
47
-
48
- function get_hit_counter($stats, $options = array())
49
- {
50
- $mmb_user_hits = get_option('user_hit_count');
51
- if (is_array($mmb_user_hits)) {
52
- end($mmb_user_hits);
53
- $last_key_date = key($mmb_user_hits);
54
- $current_date = date('Y-m-d');
55
- if ($last_key_date != $current_date)
56
- $this->set_hit_count(true);
57
- }
58
- $stats['hit_counter'] = get_option('user_hit_count');
59
-
60
- return $stats;
61
- }
62
-
63
- function get_comments($stats, $options = array())
64
- {
65
- $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
66
- $trimlen = isset($options['trimcontent']) ? (int) $options['trimcontent'] : 200;
67
-
68
- if ($nposts) {
69
- $comments = get_comments('status=hold&number=' . $nposts);
70
- if (!empty($comments)) {
71
- foreach ($comments as &$comment) {
72
- $commented_post = get_post($comment->comment_post_ID);
73
- $comment->post_title = $commented_post->post_title;
74
- $comment->comment_content = $this->trim_content($comment->comment_content, $trimlen);
75
- unset($comment->comment_author_url);
76
- unset($comment->comment_author_email);
77
- unset($comment->comment_author_IP);
78
- unset($comment->comment_date_gmt);
79
- unset($comment->comment_karma);
80
- unset($comment->comment_agent);
81
- unset($comment->comment_type);
82
- unset($comment->comment_parent);
83
- unset($comment->user_id);
84
- }
85
- $stats['comments']['pending'] = $comments;
86
- }
87
-
88
- $comments = get_comments('status=approve&number=' . $nposts);
89
- if (!empty($comments)) {
90
- foreach ($comments as &$comment) {
91
- $commented_post = get_post($comment->comment_post_ID);
92
- $comment->post_title = $commented_post->post_title;
93
- $comment->comment_content = $this->trim_content($comment->comment_content, $trimlen);
94
- unset($comment->comment_author_url);
95
- unset($comment->comment_author_email);
96
- unset($comment->comment_author_IP);
97
- unset($comment->comment_date_gmt);
98
- unset($comment->comment_karma);
99
- unset($comment->comment_agent);
100
- unset($comment->comment_type);
101
- unset($comment->comment_parent);
102
- unset($comment->user_id);
103
- }
104
- $stats['comments']['approved'] = $comments;
105
- }
106
- }
107
- return $stats;
108
- }
109
-
110
- function get_posts($stats, $options = array())
111
- {
112
- $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
113
-
114
- if ($nposts) {
115
- $posts = get_posts('post_status=publish&numberposts=' . $nposts . '&orderby=post_date&order=desc');
116
- $recent_posts = array();
117
- if (!empty($posts)) {
118
- foreach ($posts as $id => $recent_post) {
119
- $recent = new stdClass();
120
- $recent->post_permalink = get_permalink($recent_post->ID);
121
- $recent->ID = $recent_post->ID;
122
- $recent->post_date = $recent_post->post_date;
123
- $recent->post_title = $recent_post->post_title;
124
- $recent->comment_count = (int) $recent_post->comment_count;
125
- $recent_posts[] = $recent;
126
- }
127
- }
128
-
129
- $posts = get_pages('post_status=publish&numberposts=' . $nposts . '&orderby=post_date&order=desc');
130
- $recent_pages_published = array();
131
- if (!empty($posts)) {
132
- foreach ((array) $posts as $id => $recent_page_published) {
133
- $recent = new stdClass();
134
- $recent->post_permalink = get_permalink($recent_page_published->ID);
135
-
136
- $recent->ID = $recent_page_published->ID;
137
- $recent->post_date = $recent_page_published->post_date;
138
- $recent->post_title = $recent_page_published->post_title;
139
-
140
- $recent_posts[] = $recent;
141
- }
142
- }
143
- if (!empty($recent_posts)) {
144
- usort($recent_posts, array(
145
- $this,
146
- 'cmp_posts_worker'
147
- ));
148
- $stats['posts'] = array_slice($recent_posts, 0, $nposts);
149
- }
150
- }
151
- return $stats;
152
- }
153
-
154
- function get_drafts($stats, $options = array())
155
- {
156
- $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
157
-
158
- if ($nposts) {
159
- $drafts = get_posts('post_status=draft&numberposts=' . $nposts . '&orderby=post_date&order=desc');
160
- $recent_drafts = array();
161
- if (!empty($drafts)) {
162
- foreach ($drafts as $id => $recent_draft) {
163
- $recent = new stdClass();
164
- $recent->post_permalink = get_permalink($recent_draft->ID);
165
- $recent->ID = $recent_draft->ID;
166
- $recent->post_date = $recent_draft->post_date;
167
- $recent->post_title = $recent_draft->post_title;
168
-
169
- $recent_drafts[] = $recent;
170
- }
171
- }
172
- $drafts = get_pages('post_status=draft&numberposts=' . $nposts . '&orderby=post_date&order=desc');
173
- $recent_pages_drafts = array();
174
- if (!empty($drafts)) {
175
- foreach ((array) $drafts as $id => $recent_pages_draft) {
176
- $recent = new stdClass();
177
- $recent->post_permalink = get_permalink($recent_pages_draft->ID);
178
- $recent->ID = $recent_pages_draft->ID;
179
- $recent->post_date = $recent_pages_draft->post_date;
180
- $recent->post_title = $recent_pages_draft->post_title;
181
-
182
- $recent_drafts[] = $recent;
183
- }
184
- }
185
- if (!empty($recent_drafts)) {
186
- usort($recent_drafts, array(
187
- $this,
188
- 'cmp_posts_worker'
189
- ));
190
- $stats['drafts'] = array_slice($recent_drafts, 0, $nposts);
191
- }
192
- }
193
- return $stats;
194
- }
195
-
196
- function get_scheduled($stats, $options = array())
197
- {
198
- $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
199
-
200
- if ($nposts) {
201
- $scheduled = get_posts('post_status=future&numberposts=' . $nposts . '&orderby=post_date&order=desc');
202
- $scheduled_posts = array();
203
- if (!empty($scheduled)) {
204
- foreach ($scheduled as $id => $scheduled) {
205
- $recent = new stdClass();
206
- $recent->post_permalink = get_permalink($scheduled->ID);
207
- $recent->ID = $scheduled->ID;
208
- $recent->post_date = $scheduled->post_date;
209
- $recent->post_title = $scheduled->post_title;
210
- $scheduled_posts[] = $recent;
211
- }
212
- }
213
- $scheduled = get_pages('post_status=future&numberposts=' . $nposts . '&orderby=post_date&order=desc');
214
- $recent_pages_drafts = array();
215
- if (!empty($scheduled)) {
216
- foreach ((array) $scheduled as $id => $scheduled) {
217
- $recent = new stdClass();
218
- $recent->post_permalink = get_permalink($scheduled->ID);
219
- $recent->ID = $scheduled->ID;
220
- $recent->post_date = $scheduled->post_date;
221
- $recent->post_title = $scheduled->post_title;
222
-
223
- $scheduled_posts[] = $recent;
224
- }
225
- }
226
- if (!empty($scheduled_posts)) {
227
- usort($scheduled_posts, array(
228
- $this,
229
- 'cmp_posts_worker'
230
- ));
231
- $stats['scheduled'] = array_slice($scheduled_posts, 0, $nposts);
232
- }
233
- }
234
- return $stats;
235
- }
236
-
237
- function get_backups($stats, $options = array())
238
- {
239
- $stats['mwp_backups'] = $this->get_backup_instance()->get_backup_stats();
240
- $stats['mwp_next_backups'] = $this->get_backup_instance()->get_next_schedules();
241
-
242
- return $stats;
243
- }
244
-
245
- function get_backup_req($stats = array(), $options = array())
246
- {
247
- $stats['mwp_backups'] = $this->get_backup_instance()->get_backup_stats();
248
- $stats['mwp_next_backups'] = $this->get_backup_instance()->get_next_schedules();
249
- $stats['mwp_backup_req'] = $this->get_backup_instance()->check_backup_compat();
250
-
251
- return $stats;
252
- }
253
-
254
- function get_updates($stats, $options = array())
255
- {
256
- $upgrades = false;
257
- $premium = array();
258
- if (isset($options['premium']) && $options['premium']) {
259
- $premium_updates = array();
260
- $upgrades = apply_filters('mwp_premium_update_notification', $premium_updates);
261
- if (!empty($upgrades)) {
262
- foreach( $upgrades as $data ){
263
- if( isset($data['Name']) )
264
- $premium[] = $data['Name'];
265
- }
266
- $stats['premium_updates'] = $upgrades;
267
- $upgrades = false;
268
- }
269
- }
270
- if (isset($options['themes']) && $options['themes']) {
271
- $this->get_installer_instance();
272
- $upgrades = $this->installer_instance->get_upgradable_themes( $premium );
273
- if (!empty($upgrades)) {
274
- $stats['upgradable_themes'] = $upgrades;
275
- $upgrades = false;
276
- }
277
- }
278
-
279
- if (isset($options['plugins']) && $options['plugins']) {
280
- $this->get_installer_instance();
281
- $upgrades = $this->installer_instance->get_upgradable_plugins( $premium );
282
- if (!empty($upgrades)) {
283
- $stats['upgradable_plugins'] = $upgrades;
284
- $upgrades = false;
285
- }
286
- }
287
-
288
- return $stats;
289
- }
290
-
291
- function get_errors($stats, $options = array())
292
- {
293
- $period = isset($options['days']) ? (int) $options['days'] * 86400 : 86400;
294
- $maxerrors = isset($options['max']) ? (int) $options['max'] : 20;
295
- $errors = array();
296
- if (isset($options['get']) && $options['get'] == true) {
297
- if (function_exists('ini_get')) {
298
- $logpath = ini_get('error_log');
299
- if (!empty($logpath) && file_exists($logpath)) {
300
- $logfile = @fopen($logpath, 'r');
301
- if ($logfile && filesize($logpath) > 0) {
302
- $maxlines = 1;
303
- $linesize = -4096;
304
- $lines = array();
305
- $line = true;
306
- while ($line !== false) {
307
- if( fseek($logfile, ($maxlines * $linesize), SEEK_END) !== -1){
308
- $maxlines++;
309
- if ($line) {
310
- $line = fread($logfile, ($linesize * -1)) . $line;
311
-
312
- foreach ((array) preg_split("/(\r|\n|\r\n)/U", $line) as $l) {
313
- preg_match('/\[(.*)\]/Ui', $l, $match);
314
- if (!empty($match)) {
315
- $key = str_replace($match[0], '', $l);
316
- if(!isset($errors[$key])){
317
- $errors[$key] = 1;
318
- } else {
319
- $errors[$key] = $errors[$key] + 1;
320
- }
321
-
322
- if ((strtotime($match[1]) < ((int) time() - $period)) || count($errors) >= $maxerrors) {
323
- $line = false;
324
- break;
325
- }
326
- }
327
- }
328
- }
329
- } else
330
- break;
331
- }
332
- }
333
- if (!empty($errors)){
334
- $stats['errors'] = $errors;
335
- $stats['logpath'] = $logpath;
336
- $stats['logsize'] = @filesize($logpath);
337
- }
338
- }
339
- }
340
- }
341
-
342
- return $stats;
343
- }
344
-
345
- function pre_init_stats($params)
346
- {
347
- global $_mmb_item_filter;
348
-
349
- include_once(ABSPATH . 'wp-includes/update.php');
350
- include_once(ABSPATH . '/wp-admin/includes/update.php');
351
-
352
- $stats = $this->mmb_parse_action_params('pre_init_stats', $params, $this);
353
- $num = extract($params);
354
-
355
- if ($refresh == 'transient') {
356
- $current = $this->mmb_get_transient('update_core');
357
- if (isset($current->last_checked) || get_option('mmb_forcerefresh')) {
358
- update_option('mmb_forcerefresh', false);
359
- if (time() - $current->last_checked > 14400) {
360
- @wp_version_check();
361
- @wp_update_plugins();
362
- @wp_update_themes();
363
- }
364
- }
365
- }
366
-
367
- global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $wp_version, $wp_local_package;
368
-
369
- $stats['worker_version'] = MMB_WORKER_VERSION;
370
- $stats['wordpress_version'] = $wp_version;
371
- $stats['wordpress_locale_pckg'] = $wp_local_package;
372
- $stats['php_version'] = phpversion();
373
- $stats['mysql_version'] = $wpdb->db_version();
374
- $stats['wp_multisite'] = $this->mmb_multisite;
375
- $stats['network_install'] = $this->network_admin_install;
376
-
377
- if ( !function_exists('get_filesystem_method') )
378
- include_once(ABSPATH . 'wp-admin/includes/file.php');
379
- $mmode = get_option('mwp_maintenace_mode');
380
-
381
- if( !empty($mmode) && isset($mmode['active']) && $mmode['active'] == true){
382
- $stats['maintenance'] = true;
383
- }
384
- $stats['writable'] = $this->is_server_writable();
385
-
386
- return $stats;
387
- }
388
-
389
- function get($params)
390
- {
391
- global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $_mmb_item_filter;
392
-
393
- include_once(ABSPATH . 'wp-includes/update.php');
394
- include_once(ABSPATH . '/wp-admin/includes/update.php');
395
-
396
- $stats = $this->mmb_parse_action_params('get', $params, $this);
397
- $update_check = array();
398
- $num = extract($params);
399
- if ($refresh == 'transient') {
400
- $update_check = apply_filters('mwp_premium_update_check', $update_check);
401
- if (!empty($update_check)) {
402
- foreach ($update_check as $update) {
403
- if (is_array($update['callback'])) {
404
- $update_result = call_user_func(array(
405
- $update['callback'][0],
406
- $update['callback'][1]
407
- ));
408
- } else if (is_string($update['callback'])) {
409
- $update_result = call_user_func($update['callback']);
410
- }
411
- }
412
- }
413
- }
414
-
415
- if ($this->mmb_multisite) {
416
- $stats = $this->get_multisite($stats);
417
- }
418
-
419
- update_option('mmb_stats_filter', $params['item_filter']['get_stats']);
420
- $stats = apply_filters('mmb_stats_filter', $stats);
421
- return $stats;
422
- }
423
-
424
- function get_multisite($stats = array())
425
- {
426
- global $current_user, $wpdb;
427
- $user_blogs = get_blogs_of_user( $current_user->ID );
428
- $network_blogs = $wpdb->get_results( $wpdb->prepare("select `blog_id`, `site_id` from `{$wpdb->blogs}`") );
429
- if ($this->network_admin_install == '1' && is_super_admin()) {
430
- if (!empty($network_blogs)) {
431
- $blogs = array();
432
- foreach ( $network_blogs as $details) {
433
- if($details->site_id == $details->blog_id)
434
- continue;
435
- else {
436
- $data = get_blog_details($details->blog_id);
437
- if(in_array($details->blog_id, array_keys($user_blogs)))
438
- $stats['network_blogs'][] = $data->siteurl;
439
- else {
440
- $user = get_users( array( 'blog_id' => $details->blog_id, 'number' => 1) );
441
- if( !empty($user) )
442
- $stats['other_blogs'][$data->siteurl] = $user[0]->user_login;
443
- }
444
- }
445
- }
446
- }
447
- }
448
- return $stats;
449
- }
450
-
451
- function get_comments_stats()
452
- {
453
- $num_pending_comments = 3;
454
- $num_approved_comments = 3;
455
- $pending_comments = get_comments('status=hold&number=' . $num_pending_comments);
456
- foreach ($pending_comments as &$comment) {
457
- $commented_post = get_post($comment->comment_post_ID);
458
- $comment->post_title = $commented_post->post_title;
459
- }
460
- $stats['comments']['pending'] = $pending_comments;
461
-
462
-
463
- $approved_comments = get_comments('status=approve&number=' . $num_approved_comments);
464
- foreach ($approved_comments as &$comment) {
465
- $commented_post = get_post($comment->comment_post_ID);
466
- $comment->post_title = $commented_post->post_title;
467
- }
468
- $stats['comments']['approved'] = $approved_comments;
469
-
470
- return $stats;
471
- }
472
-
473
- function get_initial_stats()
474
- {
475
- global $mmb_plugin_dir;
476
-
477
- $stats = array();
478
-
479
- $stats['email'] = get_option('admin_email');
480
- $stats['no_openssl'] = $this->get_random_signature();
481
- $stats['content_path'] = WP_CONTENT_DIR;
482
- $stats['worker_path'] = $mmb_plugin_dir;
483
- $stats['worker_version'] = MMB_WORKER_VERSION;
484
- $stats['site_title'] = get_bloginfo('name');
485
- $stats['site_tagline'] = get_bloginfo('description');
486
- $stats['site_home'] = get_option('home');
487
- $stats['admin_url'] = admin_url();
488
- $stats['wp_multisite'] = $this->mmb_multisite;
489
- $stats['network_install'] = $this->network_admin_install;
490
-
491
- if ($this->mmb_multisite) {
492
- $details = get_blog_details($this->mmb_multisite);
493
- if (isset($details->site_id)) {
494
- $details = get_blog_details($details->site_id);
495
- if (isset($details->siteurl))
496
- $stats['network_parent'] = $details->siteurl;
497
- }
498
- }
499
- if (!function_exists('get_filesystem_method'))
500
- include_once(ABSPATH . 'wp-admin/includes/file.php');
501
-
502
- $stats['writable'] = $this->is_server_writable();
503
-
504
- return $stats;
505
- }
506
-
507
- function set_hit_count($fix_count = false)
508
- {
509
- global $mmb_core;
510
- $uptime_robot = array("74.86.158.106", "74.86.179.130", "74.86.179.131", "46.137.190.132", "122.248.234.23", "74.86.158.107"); //don't let uptime robot to affect visit count
511
-
512
- if ($fix_count || (!is_admin() && !MMB_Stats::is_bot() && !isset($_GET['doing_wp_cron']) && !in_array($_SERVER['REMOTE_ADDR'],$uptime_robot)) ) {
513
-
514
- $date = date('Y-m-d');
515
- $user_hit_count = (array) get_option('user_hit_count');
516
- if (!$user_hit_count) {
517
- $user_hit_count[$date] = 1;
518
- update_option('user_hit_count', $user_hit_count);
519
- } else {
520
- $dated_keys = array_keys($user_hit_count);
521
- $last_visit_date = $dated_keys[count($dated_keys) - 1];
522
-
523
- $days = intval((strtotime($date) - strtotime($last_visit_date)) / 60 / 60 / 24);
524
-
525
- if ($days > 1) {
526
- $date_to_add = date('Y-m-d', strtotime($last_visit_date));
527
-
528
- for ($i = 1; $i < $days; $i++) {
529
- if (count($user_hit_count) > 14) {
530
- $shifted = @array_shift($user_hit_count);
531
- }
532
-
533
- $next_key = strtotime('+1 day', strtotime($date_to_add));
534
- if ($next_key == $date) {
535
- break;
536
- } else {
537
- $user_hit_count[$next_key] = 0;
538
- }
539
- }
540
-
541
- }
542
-
543
- if (!isset($user_hit_count[$date])) {
544
- $user_hit_count[$date] = 0;
545
- }
546
- if (!$fix_count)
547
- $user_hit_count[$date] = ((int) $user_hit_count[$date]) + 1;
548
-
549
- if (count($user_hit_count) > 14) {
550
- $shifted = @array_shift($user_hit_count);
551
- }
552
-
553
- update_option('user_hit_count', $user_hit_count);
554
-
555
- }
556
- }
557
- }
558
-
559
- function get_hit_count()
560
- {
561
- // Check if there are no hits on last key date
562
- $mmb_user_hits = get_option('user_hit_count');
563
- if (is_array($mmb_user_hits)) {
564
- end($mmb_user_hits);
565
- $last_key_date = key($mmb_user_hits);
566
- $current_date = date('Y-m-d');
567
- if ($last_key_date != $curent_date)
568
- $this->set_hit_count(true);
569
- }
570
-
571
- return get_option('user_hit_count');
572
- }
573
-
574
- function is_bot()
575
- {
576
- $agent = $_SERVER['HTTP_USER_AGENT'];
577
-
578
- if ($agent == '')
579
- return false;
580
-
581
- $bot_list = array(
582
- "Teoma",
583
- "alexa",
584
- "froogle",
585
- "Gigabot",
586
- "inktomi",
587
- "looksmart",
588
- "URL_Spider_SQL",
589
- "Firefly",
590
- "NationalDirectory",
591
- "Ask Jeeves",
592
- "TECNOSEEK",
593
- "InfoSeek",
594
- "WebFindBot",
595
- "girafabot",
596
- "crawler",
597
- "www.galaxy.com",
598
- "Googlebot",
599
- "Scooter",
600
- "Slurp",
601
- "msnbot",
602
- "appie",
603
- "FAST",
604
- "WebBug",
605
- "Spade",
606
- "ZyBorg",
607
- "rabaz",
608
- "Baiduspider",
609
- "Feedfetcher-Google",
610
- "TechnoratiSnoop",
611
- "Rankivabot",
612
- "Mediapartners-Google",
613
- "Sogou web spider",
614
- "WebAlta Crawler",
615
- "aolserver"
616
- );
617
-
618
- foreach ($bot_list as $bot)
619
- if (strpos($agent, $bot) !== false)
620
- return true;
621
-
622
- return false;
623
- }
624
-
625
-
626
- function set_notifications($params)
627
- {
628
- if (empty($params))
629
- return false;
630
-
631
- extract($params);
632
-
633
- if (!isset($delete)) {
634
- $mwp_notifications = array(
635
- 'plugins' => $plugins,
636
- 'themes' => $themes,
637
- 'wp' => $wp,
638
- 'backups' => $backups,
639
- 'url' => $url,
640
- 'notification_key' => $notification_key
641
- );
642
- update_option('mwp_notifications', $mwp_notifications);
643
- } else {
644
- delete_option('mwp_notifications');
645
- }
646
-
647
- return true;
648
-
649
- }
650
-
651
- //Cron update check for notifications
652
- function check_notifications()
653
- {
654
- global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $wp_version, $wp_local_package;
655
-
656
- $mwp_notifications = get_option('mwp_notifications', true);
657
-
658
- $args = array();
659
- $updates = array();
660
- $send = 0;
661
- if (is_array($mwp_notifications) && $mwp_notifications != false) {
662
- include_once(ABSPATH . 'wp-includes/update.php');
663
- include_once(ABSPATH . '/wp-admin/includes/update.php');
664
- extract($mwp_notifications);
665
-
666
- //Check wordpress core updates
667
- if ($wp) {
668
- @wp_version_check();
669
- if (function_exists('get_core_updates')) {
670
- $wp_updates = get_core_updates();
671
- if (!empty($wp_updates)) {
672
- $current_transient = $wp_updates[0];
673
- if ($current_transient->response == "development" || version_compare($wp_version, $current_transient->current, '<')) {
674
- $current_transient->current_version = $wp_version;
675
- $updates['core_updates'] = $current_transient;
676
- } else
677
- $updates['core_updates'] = array();
678
- } else
679
- $updates['core_updates'] = array();
680
- }
681
- }
682
-
683
- //Check plugin updates
684
- if ($plugins) {
685
- @wp_update_plugins();
686
- $this->get_installer_instance();
687
- $updates['upgradable_plugins'] = $this->installer_instance->get_upgradable_plugins();
688
- }
689
-
690
- //Check theme updates
691
- if ($themes) {
692
- @wp_update_themes();
693
- $this->get_installer_instance();
694
-
695
- $updates['upgradable_themes'] = $this->installer_instance->get_upgradable_themes();
696
- }
697
-
698
- if ($backups) {
699
- $this->get_backup_instance();
700
- $backups = $this->backup_instance->get_backup_stats();
701
- $updates['backups'] = $backups;
702
- foreach ($backups as $task_name => $backup_results) {
703
- foreach ($backup_results as $k => $backup) {
704
- if (isset($backups[$task_name][$k]['server']['file_path'])) {
705
- unset($backups[$task_name][$k]['server']['file_path']);
706
- }
707
- }
708
- }
709
- $updates['backups'] = $backups;
710
- }
711
-
712
-
713
- if (!empty($updates)) {
714
- $args['body']['updates'] = $updates;
715
- $args['body']['notification_key'] = $notification_key;
716
- $send = 1;
717
- }
718
-
719
- }
720
-
721
-
722
- $alert_data = get_option('mwp_pageview_alerts',true);
723
- if(is_array($alert_data) && $alert_data['alert']){
724
- $pageviews = get_option('user_hit_count');
725
- $args['body']['alerts']['pageviews'] = $pageviews;
726
- $args['body']['alerts']['site_id'] = $alert_data['site_id'];
727
- if(!isset($url)){
728
- $url = $alert_data['url'];
729
- }
730
- $send = 1;
731
- }
732
-
733
- if($send){
734
- if (!class_exists('WP_Http')) {
735
- include_once(ABSPATH . WPINC . '/class-http.php');
736
- }
737
- $result = wp_remote_post($url, $args);
738
-
739
- if (is_array($result) && $result['body'] == 'mwp_delete_alert') {
740
- delete_option('mwp_pageview_alerts');
741
- }
742
- }
743
-
744
-
745
- }
746
-
747
-
748
- function cmp_posts_worker($a, $b)
749
- {
750
- return ($a->post_date < $b->post_date);
751
- }
752
-
753
- function trim_content($content = '', $length = 200)
754
- {
755
- if (function_exists('mb_strlen') && function_exists('mb_substr'))
756
- $content = (mb_strlen($content) > ($length + 3)) ? mb_substr($content, 0, $length) . '...' : $content;
757
- else
758
- $content = (strlen($content) > ($length + 3)) ? substr($content, 0, $length) . '...' : $content;
759
-
760
- return $content;
761
- }
762
-
763
- function set_alerts($args){
764
- extract($args);
765
- update_option('mwp_pageview_alerts',array('site_id' => $site_id,'alert' => $alert,'url' => $url));
766
- }
767
-
768
- public static function readd_alerts( $params = array() ){
769
- if( empty($params) || !isset($params['alerts']))
770
- return $params;
771
-
772
- if( !empty($params['alerts']) ){
773
- update_option('mwp_pageview_alerts', $params['alerts']);
774
- unset($params['alerts']);
775
- }
776
-
777
- return $params;
778
- }
779
- }
780
-
781
- if( function_exists('add_filter') ){
782
- add_filter( 'mwp_website_add', 'MMB_Stats::readd_alerts' );
783
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * stats.class.php
5
+ *
6
+ * Get Site Stats
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "stats.class.php"):
13
+ exit;
14
+ endif;
15
+
16
+ class MMB_Stats extends MMB_Core
17
+ {
18
+ function __construct()
19
+ {
20
+ parent::__construct();
21
+ }
22
+
23
+ /*************************************************************
24
+ * FACADE functions
25
+ * (functions to be called after a remote call from Master)
26
+ **************************************************************/
27
+
28
+ function get_core_update($stats, $options = array())
29
+ {
30
+ global $wp_version;
31
+
32
+ if (isset($options['core']) && $options['core']) {
33
+ $core = $this->mmb_get_transient('update_core');
34
+ if (isset($core->updates) && !empty($core->updates)) {
35
+ $current_transient = $core->updates[0];
36
+ if ($current_transient->response == "development" || version_compare($wp_version, $current_transient->current, '<')) {
37
+ $current_transient->current_version = $wp_version;
38
+ $stats['core_updates'] = $current_transient;
39
+ } else
40
+ $stats['core_updates'] = false;
41
+ } else
42
+ $stats['core_updates'] = false;
43
+ }
44
+
45
+ return $stats;
46
+ }
47
+
48
+ function get_hit_counter($stats, $options = array())
49
+ {
50
+ $mmb_user_hits = get_option('user_hit_count');
51
+ if (is_array($mmb_user_hits)) {
52
+ end($mmb_user_hits);
53
+ $last_key_date = key($mmb_user_hits);
54
+ $current_date = date('Y-m-d');
55
+ if ($last_key_date != $current_date)
56
+ $this->set_hit_count(true);
57
+ }
58
+ $stats['hit_counter'] = get_option('user_hit_count');
59
+
60
+ return $stats;
61
+ }
62
+
63
+ function get_comments($stats, $options = array())
64
+ {
65
+ $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
66
+ $trimlen = isset($options['trimcontent']) ? (int) $options['trimcontent'] : 200;
67
+
68
+ if ($nposts) {
69
+ $comments = get_comments('status=hold&number=' . $nposts);
70
+ if (!empty($comments)) {
71
+ foreach ($comments as &$comment) {
72
+ $commented_post = get_post($comment->comment_post_ID);
73
+ $comment->post_title = $commented_post->post_title;
74
+ $comment->comment_content = $this->trim_content($comment->comment_content, $trimlen);
75
+ unset($comment->comment_author_url);
76
+ unset($comment->comment_author_email);
77
+ unset($comment->comment_author_IP);
78
+ unset($comment->comment_date_gmt);
79
+ unset($comment->comment_karma);
80
+ unset($comment->comment_agent);
81
+ unset($comment->comment_type);
82
+ unset($comment->comment_parent);
83
+ unset($comment->user_id);
84
+ }
85
+ $stats['comments']['pending'] = $comments;
86
+ }
87
+
88
+ $comments = get_comments('status=approve&number=' . $nposts);
89
+ if (!empty($comments)) {
90
+ foreach ($comments as &$comment) {
91
+ $commented_post = get_post($comment->comment_post_ID);
92
+ $comment->post_title = $commented_post->post_title;
93
+ $comment->comment_content = $this->trim_content($comment->comment_content, $trimlen);
94
+ unset($comment->comment_author_url);
95
+ unset($comment->comment_author_email);
96
+ unset($comment->comment_author_IP);
97
+ unset($comment->comment_date_gmt);
98
+ unset($comment->comment_karma);
99
+ unset($comment->comment_agent);
100
+ unset($comment->comment_type);
101
+ unset($comment->comment_parent);
102
+ unset($comment->user_id);
103
+ }
104
+ $stats['comments']['approved'] = $comments;
105
+ }
106
+ }
107
+ return $stats;
108
+ }
109
+
110
+ function get_posts($stats, $options = array())
111
+ {
112
+ $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
113
+
114
+ if ($nposts) {
115
+ $posts = get_posts('post_status=publish&numberposts=' . $nposts . '&orderby=post_date&order=desc');
116
+ $recent_posts = array();
117
+ if (!empty($posts)) {
118
+ foreach ($posts as $id => $recent_post) {
119
+ $recent = new stdClass();
120
+ $recent->post_permalink = get_permalink($recent_post->ID);
121
+ $recent->ID = $recent_post->ID;
122
+ $recent->post_date = $recent_post->post_date;
123
+ $recent->post_title = $recent_post->post_title;
124
+ $recent->post_type = $recent_post->post_type;
125
+ $recent->comment_count = (int) $recent_post->comment_count;
126
+ $recent_posts[] = $recent;
127
+ }
128
+ }
129
+
130
+ $posts = get_pages('post_status=publish&numberposts=' . $nposts . '&orderby=post_date&order=desc');
131
+ $recent_pages_published = array();
132
+ if (!empty($posts)) {
133
+ foreach ((array) $posts as $id => $recent_page_published) {
134
+ $recent = new stdClass();
135
+ $recent->post_permalink = get_permalink($recent_page_published->ID);
136
+ $recent->post_type = $recent_page_published->post_type;
137
+ $recent->ID = $recent_page_published->ID;
138
+ $recent->post_date = $recent_page_published->post_date;
139
+ $recent->post_title = $recent_page_published->post_title;
140
+
141
+ $recent_posts[] = $recent;
142
+ }
143
+ }
144
+ if (!empty($recent_posts)) {
145
+ usort($recent_posts, array(
146
+ $this,
147
+ 'cmp_posts_worker'
148
+ ));
149
+ $stats['posts'] = array_slice($recent_posts, 0, $nposts);
150
+ }
151
+ }
152
+ return $stats;
153
+ }
154
+
155
+ function get_drafts($stats, $options = array())
156
+ {
157
+ $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
158
+
159
+ if ($nposts) {
160
+ $drafts = get_posts('post_status=draft&numberposts=' . $nposts . '&orderby=post_date&order=desc');
161
+ $recent_drafts = array();
162
+ if (!empty($drafts)) {
163
+ foreach ($drafts as $id => $recent_draft) {
164
+ $recent = new stdClass();
165
+ $recent->post_permalink = get_permalink($recent_draft->ID);
166
+ $recent->post_type = $recent_draft->post_type;
167
+ $recent->ID = $recent_draft->ID;
168
+ $recent->post_date = $recent_draft->post_date;
169
+ $recent->post_title = $recent_draft->post_title;
170
+
171
+ $recent_drafts[] = $recent;
172
+ }
173
+ }
174
+ $drafts = get_pages('post_status=draft&numberposts=' . $nposts . '&orderby=post_date&order=desc');
175
+ $recent_pages_drafts = array();
176
+ if (!empty($drafts)) {
177
+ foreach ((array) $drafts as $id => $recent_pages_draft) {
178
+ $recent = new stdClass();
179
+ $recent->post_permalink = get_permalink($recent_pages_draft->ID);
180
+ $recent->ID = $recent_pages_draft->ID;
181
+ $recent->post_type = $recent_pages_draft->post_type;
182
+ $recent->post_date = $recent_pages_draft->post_date;
183
+ $recent->post_title = $recent_pages_draft->post_title;
184
+
185
+ $recent_drafts[] = $recent;
186
+ }
187
+ }
188
+ if (!empty($recent_drafts)) {
189
+ usort($recent_drafts, array(
190
+ $this,
191
+ 'cmp_posts_worker'
192
+ ));
193
+ $stats['drafts'] = array_slice($recent_drafts, 0, $nposts);
194
+ }
195
+ }
196
+ return $stats;
197
+ }
198
+
199
+ function get_scheduled($stats, $options = array())
200
+ {
201
+ $nposts = isset($options['numberposts']) ? (int) $options['numberposts'] : 20;
202
+
203
+ if ($nposts) {
204
+ $scheduled = get_posts('post_status=future&numberposts=' . $nposts . '&orderby=post_date&order=desc');
205
+ $scheduled_posts = array();
206
+ if (!empty($scheduled)) {
207
+ foreach ($scheduled as $id => $scheduled) {
208
+ $recent = new stdClass();
209
+ $recent->post_permalink = get_permalink($scheduled->ID);
210
+ $recent->ID = $scheduled->ID;
211
+ $recent->post_date = $scheduled->post_date;
212
+ $recent->post_type = $scheduled->post_type;
213
+ $recent->post_title = $scheduled->post_title;
214
+ $scheduled_posts[] = $recent;
215
+ }
216
+ }
217
+ $scheduled = get_pages('post_status=future&numberposts=' . $nposts . '&orderby=post_date&order=desc');
218
+ $recent_pages_drafts = array();
219
+ if (!empty($scheduled)) {
220
+ foreach ((array) $scheduled as $id => $scheduled) {
221
+ $recent = new stdClass();
222
+ $recent->post_permalink = get_permalink($scheduled->ID);
223
+ $recent->ID = $scheduled->ID;
224
+ $recent->post_type = $scheduled->post_type;
225
+ $recent->post_date = $scheduled->post_date;
226
+ $recent->post_title = $scheduled->post_title;
227
+
228
+ $scheduled_posts[] = $recent;
229
+ }
230
+ }
231
+ if (!empty($scheduled_posts)) {
232
+ usort($scheduled_posts, array(
233
+ $this,
234
+ 'cmp_posts_worker'
235
+ ));
236
+ $stats['scheduled'] = array_slice($scheduled_posts, 0, $nposts);
237
+ }
238
+ }
239
+ return $stats;
240
+ }
241
+
242
+ function get_backups($stats, $options = array())
243
+ {
244
+ $stats['mwp_backups'] = $this->get_backup_instance()->get_backup_stats();
245
+ $stats['mwp_next_backups'] = $this->get_backup_instance()->get_next_schedules();
246
+
247
+ return $stats;
248
+ }
249
+
250
+ function get_backup_req($stats = array(), $options = array())
251
+ {
252
+ $stats['mwp_backups'] = $this->get_backup_instance()->get_backup_stats();
253
+ $stats['mwp_next_backups'] = $this->get_backup_instance()->get_next_schedules();
254
+ $stats['mwp_backup_req'] = $this->get_backup_instance()->check_backup_compat();
255
+
256
+ return $stats;
257
+ }
258
+
259
+ function get_updates($stats, $options = array())
260
+ {
261
+ $upgrades = false;
262
+ $premium = array();
263
+ if (isset($options['premium']) && $options['premium']) {
264
+ $premium_updates = array();
265
+ $upgrades = apply_filters('mwp_premium_update_notification', $premium_updates);
266
+ if (!empty($upgrades)) {
267
+ foreach( $upgrades as $data ){
268
+ if( isset($data['Name']) )
269
+ $premium[] = $data['Name'];
270
+ }
271
+ $stats['premium_updates'] = $upgrades;
272
+ $upgrades = false;
273
+ }
274
+ }
275
+ if (isset($options['themes']) && $options['themes']) {
276
+ $this->get_installer_instance();
277
+ $upgrades = $this->installer_instance->get_upgradable_themes( $premium );
278
+ if (!empty($upgrades)) {
279
+ $stats['upgradable_themes'] = $upgrades;
280
+ $upgrades = false;
281
+ }
282
+ }
283
+
284
+ if (isset($options['plugins']) && $options['plugins']) {
285
+ $this->get_installer_instance();
286
+ $upgrades = $this->installer_instance->get_upgradable_plugins( $premium );
287
+ if (!empty($upgrades)) {
288
+ $stats['upgradable_plugins'] = $upgrades;
289
+ $upgrades = false;
290
+ }
291
+ }
292
+
293
+ return $stats;
294
+ }
295
+
296
+ function get_errors($stats, $options = array())
297
+ {
298
+ $period = isset($options['days']) ? (int) $options['days'] * 86400 : 86400;
299
+ $maxerrors = isset($options['max']) ? (int) $options['max'] : 20;
300
+ $errors = array();
301
+ if (isset($options['get']) && $options['get'] == true) {
302
+ if (function_exists('ini_get')) {
303
+ $logpath = ini_get('error_log');
304
+ if (!empty($logpath) && file_exists($logpath)) {
305
+ $logfile = @fopen($logpath, 'r');
306
+ if ($logfile && filesize($logpath) > 0) {
307
+ $maxlines = 1;
308
+ $linesize = -4096;
309
+ $lines = array();
310
+ $line = true;
311
+ while ($line !== false) {
312
+ if( fseek($logfile, ($maxlines * $linesize), SEEK_END) !== -1){
313
+ $maxlines++;
314
+ if ($line) {
315
+ $line = fread($logfile, ($linesize * -1)) . $line;
316
+
317
+ foreach ((array) preg_split("/(\r|\n|\r\n)/U", $line) as $l) {
318
+ preg_match('/\[(.*)\]/Ui', $l, $match);
319
+ if (!empty($match)) {
320
+ $key = str_replace($match[0], '', $l);
321
+ if(!isset($errors[$key])){
322
+ $errors[$key] = 1;
323
+ } else {
324
+ $errors[$key] = $errors[$key] + 1;
325
+ }
326
+
327
+ if ((strtotime($match[1]) < ((int) time() - $period)) || count($errors) >= $maxerrors) {
328
+ $line = false;
329
+ break;
330
+ }
331
+ }
332
+ }
333
+ }
334
+ } else
335
+ break;
336
+ }
337
+ }
338
+ if (!empty($errors)){
339
+ $stats['errors'] = $errors;
340
+ $stats['logpath'] = $logpath;
341
+ $stats['logsize'] = @filesize($logpath);
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ return $stats;
348
+ }
349
+
350
+ function pre_init_stats($params)
351
+ {
352
+ global $_mmb_item_filter;
353
+
354
+ include_once(ABSPATH . 'wp-includes/update.php');
355
+ include_once(ABSPATH . '/wp-admin/includes/update.php');
356
+
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')) {
363
+ update_option('mmb_forcerefresh', false);
364
+ if (time() - $current->last_checked > 14400) {
365
+ @wp_version_check();
366
+ @wp_update_plugins();
367
+ @wp_update_themes();
368
+ }
369
+ }
370
+ }
371
+
372
+ global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $wp_version, $wp_local_package;
373
+
374
+ $stats['worker_version'] = MMB_WORKER_VERSION;
375
+ $stats['wordpress_version'] = $wp_version;
376
+ $stats['wordpress_locale_pckg'] = $wp_local_package;
377
+ $stats['php_version'] = phpversion();
378
+ $stats['mysql_version'] = $wpdb->db_version();
379
+ $stats['wp_multisite'] = $this->mmb_multisite;
380
+ $stats['network_install'] = $this->network_admin_install;
381
+
382
+ if ( !function_exists('get_filesystem_method') )
383
+ include_once(ABSPATH . 'wp-admin/includes/file.php');
384
+ $mmode = get_option('mwp_maintenace_mode');
385
+
386
+ if( !empty($mmode) && isset($mmode['active']) && $mmode['active'] == true){
387
+ $stats['maintenance'] = true;
388
+ }
389
+ $stats['writable'] = $this->is_server_writable();
390
+
391
+ return $stats;
392
+ }
393
+
394
+ function get($params)
395
+ {
396
+ global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $_mmb_item_filter;
397
+
398
+ include_once(ABSPATH . 'wp-includes/update.php');
399
+ include_once(ABSPATH . '/wp-admin/includes/update.php');
400
+
401
+ $stats = $this->mmb_parse_action_params('get', $params, $this);
402
+ $update_check = array();
403
+ $num = extract($params);
404
+ if ($refresh == 'transient') {
405
+ $update_check = apply_filters('mwp_premium_update_check', $update_check);
406
+ if (!empty($update_check)) {
407
+ foreach ($update_check as $update) {
408
+ if (is_array($update['callback'])) {
409
+ $update_result = call_user_func(array(
410
+ $update['callback'][0],
411
+ $update['callback'][1]
412
+ ));
413
+ } else if (is_string($update['callback'])) {
414
+ $update_result = call_user_func($update['callback']);
415
+ }
416
+ }
417
+ }
418
+ }
419
+
420
+ if ($this->mmb_multisite) {
421
+ $stats = $this->get_multisite($stats);
422
+ }
423
+
424
+ update_option('mmb_stats_filter', $params['item_filter']['get_stats']);
425
+ $stats = apply_filters('mmb_stats_filter', $stats);
426
+ return $stats;
427
+ }
428
+
429
+ function get_multisite($stats = array())
430
+ {
431
+ global $current_user, $wpdb;
432
+ $user_blogs = get_blogs_of_user( $current_user->ID );
433
+ $network_blogs = $wpdb->get_results( $wpdb->prepare("select `blog_id`, `site_id` from `{$wpdb->blogs}`") );
434
+ if ($this->network_admin_install == '1' && is_super_admin()) {
435
+ if (!empty($network_blogs)) {
436
+ $blogs = array();
437
+ foreach ( $network_blogs as $details) {
438
+ if($details->site_id == $details->blog_id)
439
+ continue;
440
+ else {
441
+ $data = get_blog_details($details->blog_id);
442
+ if(in_array($details->blog_id, array_keys($user_blogs)))
443
+ $stats['network_blogs'][] = $data->siteurl;
444
+ else {
445
+ $user = get_users( array( 'blog_id' => $details->blog_id, 'number' => 1) );
446
+ if( !empty($user) )
447
+ $stats['other_blogs'][$data->siteurl] = $user[0]->user_login;
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ return $stats;
454
+ }
455
+
456
+ function get_comments_stats()
457
+ {
458
+ $num_pending_comments = 3;
459
+ $num_approved_comments = 3;
460
+ $pending_comments = get_comments('status=hold&number=' . $num_pending_comments);
461
+ foreach ($pending_comments as &$comment) {
462
+ $commented_post = get_post($comment->comment_post_ID);
463
+ $comment->post_title = $commented_post->post_title;
464
+ }
465
+ $stats['comments']['pending'] = $pending_comments;
466
+
467
+
468
+ $approved_comments = get_comments('status=approve&number=' . $num_approved_comments);
469
+ foreach ($approved_comments as &$comment) {
470
+ $commented_post = get_post($comment->comment_post_ID);
471
+ $comment->post_title = $commented_post->post_title;
472
+ }
473
+ $stats['comments']['approved'] = $approved_comments;
474
+
475
+ return $stats;
476
+ }
477
+
478
+ function get_initial_stats()
479
+ {
480
+ global $mmb_plugin_dir;
481
+
482
+ $stats = array();
483
+
484
+ $stats['email'] = get_option('admin_email');
485
+ $stats['no_openssl'] = $this->get_random_signature();
486
+ $stats['content_path'] = WP_CONTENT_DIR;
487
+ $stats['worker_path'] = $mmb_plugin_dir;
488
+ $stats['worker_version'] = MMB_WORKER_VERSION;
489
+ $stats['site_title'] = get_bloginfo('name');
490
+ $stats['site_tagline'] = get_bloginfo('description');
491
+ $stats['db_name'] = $this->get_active_db();
492
+ $stats['site_home'] = get_option('home');
493
+ $stats['admin_url'] = admin_url();
494
+ $stats['wp_multisite'] = $this->mmb_multisite;
495
+ $stats['network_install'] = $this->network_admin_install;
496
+
497
+ if ($this->mmb_multisite) {
498
+ $details = get_blog_details($this->mmb_multisite);
499
+ if (isset($details->site_id)) {
500
+ $details = get_blog_details($details->site_id);
501
+ if (isset($details->siteurl))
502
+ $stats['network_parent'] = $details->siteurl;
503
+ }
504
+ }
505
+ if (!function_exists('get_filesystem_method'))
506
+ include_once(ABSPATH . 'wp-admin/includes/file.php');
507
+
508
+ $stats['writable'] = $this->is_server_writable();
509
+
510
+ return $stats;
511
+ }
512
+
513
+ function get_active_db(){
514
+ global $wpdb;
515
+ $sql='SELECT DATABASE() as db_name';
516
+
517
+ $sqlresult = $wpdb->get_row($sql);
518
+ $active_db=$sqlresult->db_name;
519
+
520
+ return $active_db;
521
+
522
+ }
523
+
524
+ function set_hit_count($fix_count = false)
525
+ {
526
+ global $mmb_core;
527
+ $uptime_robot = array("74.86.158.106", "74.86.179.130", "74.86.179.131", "46.137.190.132", "122.248.234.23", "74.86.158.107"); //don't let uptime robot to affect visit count
528
+
529
+ if ($fix_count || (!is_admin() && !MMB_Stats::is_bot() && !isset($_GET['doing_wp_cron']) && !in_array($_SERVER['REMOTE_ADDR'],$uptime_robot)) ) {
530
+
531
+ $date = date('Y-m-d');
532
+ $user_hit_count = (array) get_option('user_hit_count');
533
+ if (!$user_hit_count) {
534
+ $user_hit_count[$date] = 1;
535
+ update_option('user_hit_count', $user_hit_count);
536
+ } else {
537
+ $dated_keys = array_keys($user_hit_count);
538
+ $last_visit_date = $dated_keys[count($dated_keys) - 1];
539
+
540
+ $days = intval((strtotime($date) - strtotime($last_visit_date)) / 60 / 60 / 24);
541
+
542
+ if ($days > 1) {
543
+ $date_to_add = date('Y-m-d', strtotime($last_visit_date));
544
+
545
+ for ($i = 1; $i < $days; $i++) {
546
+ if (count($user_hit_count) > 14) {
547
+ $shifted = @array_shift($user_hit_count);
548
+ }
549
+
550
+ $next_key = strtotime('+1 day', strtotime($date_to_add));
551
+ if ($next_key == $date) {
552
+ break;
553
+ } else {
554
+ $user_hit_count[$next_key] = 0;
555
+ }
556
+ }
557
+
558
+ }
559
+
560
+ if (!isset($user_hit_count[$date])) {
561
+ $user_hit_count[$date] = 0;
562
+ }
563
+ if (!$fix_count)
564
+ $user_hit_count[$date] = ((int) $user_hit_count[$date]) + 1;
565
+
566
+ if (count($user_hit_count) > 14) {
567
+ $shifted = @array_shift($user_hit_count);
568
+ }
569
+
570
+ update_option('user_hit_count', $user_hit_count);
571
+
572
+ }
573
+ }
574
+ }
575
+
576
+ function get_hit_count()
577
+ {
578
+ // Check if there are no hits on last key date
579
+ $mmb_user_hits = get_option('user_hit_count');
580
+ if (is_array($mmb_user_hits)) {
581
+ end($mmb_user_hits);
582
+ $last_key_date = key($mmb_user_hits);
583
+ $current_date = date('Y-m-d');
584
+ if ($last_key_date != $curent_date)
585
+ $this->set_hit_count(true);
586
+ }
587
+
588
+ return get_option('user_hit_count');
589
+ }
590
+
591
+ function is_bot()
592
+ {
593
+ $agent = $_SERVER['HTTP_USER_AGENT'];
594
+
595
+ if ($agent == '')
596
+ return false;
597
+
598
+ $bot_list = array(
599
+ "Teoma",
600
+ "alexa",
601
+ "froogle",
602
+ "Gigabot",
603
+ "inktomi",
604
+ "looksmart",
605
+ "URL_Spider_SQL",
606
+ "Firefly",
607
+ "NationalDirectory",
608
+ "Ask Jeeves",
609
+ "TECNOSEEK",
610
+ "InfoSeek",
611
+ "WebFindBot",
612
+ "girafabot",
613
+ "crawler",
614
+ "www.galaxy.com",
615
+ "Googlebot",
616
+ "Scooter",
617
+ "Slurp",
618
+ "msnbot",
619
+ "appie",
620
+ "FAST",
621
+ "WebBug",
622
+ "Spade",
623
+ "ZyBorg",
624
+ "rabaz",
625
+ "Baiduspider",
626
+ "Feedfetcher-Google",
627
+ "TechnoratiSnoop",
628
+ "Rankivabot",
629
+ "Mediapartners-Google",
630
+ "Sogou web spider",
631
+ "WebAlta Crawler",
632
+ "aolserver"
633
+ );
634
+
635
+ foreach ($bot_list as $bot)
636
+ if (strpos($agent, $bot) !== false)
637
+ return true;
638
+
639
+ return false;
640
+ }
641
+
642
+
643
+ function set_notifications($params)
644
+ {
645
+ if (empty($params))
646
+ return false;
647
+
648
+ extract($params);
649
+
650
+ if (!isset($delete)) {
651
+ $mwp_notifications = array(
652
+ 'plugins' => $plugins,
653
+ 'themes' => $themes,
654
+ 'wp' => $wp,
655
+ 'backups' => $backups,
656
+ 'url' => $url,
657
+ 'notification_key' => $notification_key
658
+ );
659
+ update_option('mwp_notifications', $mwp_notifications);
660
+ } else {
661
+ delete_option('mwp_notifications');
662
+ }
663
+
664
+ return true;
665
+
666
+ }
667
+
668
+ //Cron update check for notifications
669
+ function check_notifications()
670
+ {
671
+ global $wpdb, $mmb_wp_version, $mmb_plugin_dir, $wp_version, $wp_local_package;
672
+
673
+ $mwp_notifications = get_option('mwp_notifications', true);
674
+
675
+ $args = array();
676
+ $updates = array();
677
+ $send = 0;
678
+ if (is_array($mwp_notifications) && $mwp_notifications != false) {
679
+ include_once(ABSPATH . 'wp-includes/update.php');
680
+ include_once(ABSPATH . '/wp-admin/includes/update.php');
681
+ extract($mwp_notifications);
682
+
683
+ //Check wordpress core updates
684
+ if ($wp) {
685
+ @wp_version_check();
686
+ if (function_exists('get_core_updates')) {
687
+ $wp_updates = get_core_updates();
688
+ if (!empty($wp_updates)) {
689
+ $current_transient = $wp_updates[0];
690
+ if ($current_transient->response == "development" || version_compare($wp_version, $current_transient->current, '<')) {
691
+ $current_transient->current_version = $wp_version;
692
+ $updates['core_updates'] = $current_transient;
693
+ } else
694
+ $updates['core_updates'] = array();
695
+ } else
696
+ $updates['core_updates'] = array();
697
+ }
698
+ }
699
+
700
+ //Check plugin updates
701
+ if ($plugins) {
702
+ @wp_update_plugins();
703
+ $this->get_installer_instance();
704
+ $updates['upgradable_plugins'] = $this->installer_instance->get_upgradable_plugins();
705
+ }
706
+
707
+ //Check theme updates
708
+ if ($themes) {
709
+ @wp_update_themes();
710
+ $this->get_installer_instance();
711
+
712
+ $updates['upgradable_themes'] = $this->installer_instance->get_upgradable_themes();
713
+ }
714
+
715
+ if ($backups) {
716
+ $this->get_backup_instance();
717
+ $backups = $this->backup_instance->get_backup_stats();
718
+ $updates['backups'] = $backups;
719
+ foreach ($backups as $task_name => $backup_results) {
720
+ foreach ($backup_results as $k => $backup) {
721
+ if (isset($backups[$task_name][$k]['server']['file_path'])) {
722
+ unset($backups[$task_name][$k]['server']['file_path']);
723
+ }
724
+ }
725
+ }
726
+ $updates['backups'] = $backups;
727
+ }
728
+
729
+
730
+ if (!empty($updates)) {
731
+ $args['body']['updates'] = $updates;
732
+ $args['body']['notification_key'] = $notification_key;
733
+ $send = 1;
734
+ }
735
+
736
+ }
737
+
738
+
739
+ $alert_data = get_option('mwp_pageview_alerts',true);
740
+ if(is_array($alert_data) && $alert_data['alert']){
741
+ $pageviews = get_option('user_hit_count');
742
+ $args['body']['alerts']['pageviews'] = $pageviews;
743
+ $args['body']['alerts']['site_id'] = $alert_data['site_id'];
744
+ if(!isset($url)){
745
+ $url = $alert_data['url'];
746
+ }
747
+ $send = 1;
748
+ }
749
+
750
+ if($send){
751
+ if (!class_exists('WP_Http')) {
752
+ include_once(ABSPATH . WPINC . '/class-http.php');
753
+ }
754
+ $result = wp_remote_post($url, $args);
755
+
756
+ if (is_array($result) && $result['body'] == 'mwp_delete_alert') {
757
+ delete_option('mwp_pageview_alerts');
758
+ }
759
+ }
760
+
761
+
762
+ }
763
+
764
+
765
+ function cmp_posts_worker($a, $b)
766
+ {
767
+ return ($a->post_date < $b->post_date);
768
+ }
769
+
770
+ function trim_content($content = '', $length = 200)
771
+ {
772
+ if (function_exists('mb_strlen') && function_exists('mb_substr'))
773
+ $content = (mb_strlen($content) > ($length + 3)) ? mb_substr($content, 0, $length) . '...' : $content;
774
+ else
775
+ $content = (strlen($content) > ($length + 3)) ? substr($content, 0, $length) . '...' : $content;
776
+
777
+ return $content;
778
+ }
779
+
780
+ function set_alerts($args){
781
+ extract($args);
782
+ update_option('mwp_pageview_alerts',array('site_id' => $site_id,'alert' => $alert,'url' => $url));
783
+ }
784
+
785
+ public static function readd_alerts( $params = array() ){
786
+ if( empty($params) || !isset($params['alerts']))
787
+ return $params;
788
+
789
+ if( !empty($params['alerts']) ){
790
+ update_option('mwp_pageview_alerts', $params['alerts']);
791
+ unset($params['alerts']);
792
+ }
793
+
794
+ return $params;
795
+ }
796
+ }
797
+
798
+ if( function_exists('add_filter') ){
799
+ add_filter( 'mwp_website_add', 'MMB_Stats::readd_alerts' );
800
+ }
801
  ?>
user.class.php CHANGED
@@ -1,215 +1,215 @@
1
- <?php
2
- /*************************************************************
3
- *
4
- * user.class.php
5
- *
6
- * Add Users
7
- *
8
- *
9
- * Copyright (c) 2011 Prelovac Media
10
- * www.prelovac.com
11
- **************************************************************/
12
- if(basename($_SERVER['SCRIPT_FILENAME']) == "user.class.php"):
13
- exit;
14
- endif;
15
- class MMB_User extends MMB_Core
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- function get_users($args){
23
- global $wpdb;
24
-
25
- //$args: $user_roles;
26
- if(empty($args))
27
- return false;
28
-
29
- extract($args);
30
-
31
- $userlevels = array();
32
- $level_strings = array();
33
- foreach($user_roles as $user_role){
34
- switch(strtolower($user_role)){
35
- case 'subscriber' : $userlevels[] = 0; $level_strings[] = $user_role; break;
36
- case 'contributor' : $userlevels[] = 1; $level_strings[] = $user_role; break;
37
- case 'author' : $userlevels[] = 2; $level_strings[] = $user_role; break;
38
- case 'editor' : $userlevels[] = 7; $level_strings[] = $user_role; break;
39
- case 'administrator' : $userlevels[] = 10; $level_strings[] = $user_role; break;
40
- default: break;
41
- }
42
- }
43
-
44
- $users = array();
45
- $userlevel_qry = "('".implode("','",$userlevels)."')";
46
- $userlevel_fallback_qry = "('%".implode("%','%",$level_strings)."%')";
47
- $field = $wpdb->prefix."capabilities";
48
-
49
- $user_metas = $wpdb->get_results("SELECT * from $wpdb->usermeta WHERE meta_key = '$field' AND meta_value IN $userlevel_fallback_qry");
50
- if($user_metas == false || empty($user_metas)){
51
- $user_metas = $wpdb->get_results("SELECT * from $wpdb->usermeta WHERE meta_key = 'wp_user_level' AND meta_value IN $userlevel_qry");
52
- }
53
-
54
- $include = array();
55
- if(is_array($user_metas) && !empty($user_metas)){
56
- foreach($user_metas as $user_meta){
57
- $include[] = $user_meta->user_id;
58
- }
59
- }
60
-
61
- $args = array();
62
- $args['include'] = $include;
63
- $args['fields'] = 'all_with_meta';
64
- $temp_users = get_users($args);
65
- $user = array();
66
- foreach ((array)$temp_users as $temp){
67
- $user['user_id'] = $temp->ID;
68
- $user['user_login'] = $temp->user_login;
69
- $user['wp_capabilities'] = array_keys($temp->$field);
70
- $users[] = $user;
71
- }
72
-
73
- return array('users' => $users);
74
- }
75
-
76
- function add_user($args)
77
- {
78
-
79
- if(!function_exists('username_exists') || !function_exists('email_exists'))
80
- include_once(ABSPATH . WPINC . '/registration.php');
81
-
82
- if(username_exists($args['user_login']))
83
- return array('error' => 'Username already exists');
84
-
85
- if (email_exists($args['user_email']))
86
- return array('error' => 'Email already exists');
87
-
88
- if(!function_exists('wp_insert_user'))
89
- include_once (ABSPATH . 'wp-admin/includes/user.php');
90
-
91
- $user_id = wp_insert_user($args);
92
-
93
- if($user_id){
94
-
95
- if($args['email_notify']){
96
- //require_once ABSPATH . WPINC . '/pluggable.php';
97
- wp_new_user_notification($user_id, $args['user_pass']);
98
- }
99
- return $user_id;
100
- }else{
101
- return array('error' => 'User not added. Please try again.');
102
- }
103
-
104
- }
105
-
106
- function edit_users($args){
107
-
108
- if(empty($args))
109
- return false;
110
- if(!function_exists('get_user_to_edit'))
111
- include_once (ABSPATH . 'wp-admin/includes/user.php');
112
- if(!function_exists('wp_update_user'))
113
- include_once (ABSPATH . WPINC.'/user.php');
114
-
115
- extract($args);
116
- //$args: $users, $new_role, $new_password, $user_edit_action
117
-
118
- $return = array();
119
- if(count($users)){
120
- foreach($users as $user){
121
- $result = '';
122
- $user_obj = $this->mmb_get_user_info( $user );
123
- if($user_obj != false){
124
- switch($user_edit_action){
125
- case 'change-password':
126
- if($new_password){
127
- $user_data = array();
128
- $userdata['user_pass'] = $new_password;
129
- $userdata['ID'] = $user_obj->ID;
130
- $result = wp_update_user($userdata);
131
- } else {
132
- $result = array('error' => 'No password provided.');
133
- }
134
- break;
135
- case 'change-role':
136
- if($new_role){
137
- if($user != $username){
138
- if(!$this->last_admin($user_obj)){
139
- $user_data = array();
140
- $userdata['ID'] = $user_obj->ID;
141
- $userdata['role'] = strtolower($new_role);
142
- $result = wp_update_user($userdata);
143
- } else {
144
- $result = array('error' => 'Cannot change role to the only one left admin user.');
145
- }
146
- } else {
147
- $result = array('error' => 'Cannot change role to user assigned for ManageWP.');
148
- }
149
- } else {
150
- $result = array('error' => 'No role provided.');
151
- }
152
- break;
153
- case 'delete-user':
154
- if($user != $username){
155
- if(!$this->last_admin($user_obj)){
156
- if($reassign_user){
157
- $to_user = $this->mmb_get_user_info( $reassign_user );
158
- if($to_user != false){
159
- $result = wp_delete_user($user_obj->ID, $to_user->ID);
160
- } else {
161
- $result = array('error' => 'User not deleted. User to reassign posts doesn\'t exist.');
162
- }
163
- } else {
164
- $result = wp_delete_user($user_obj->ID);
165
- }
166
- } else {
167
- $result = array('error' => 'Cannot delete the only one left admin user.');
168
- }
169
- } else {
170
- $result = array('error' => 'Cannot delete user assigned for ManageWP.');
171
- }
172
-
173
- break;
174
- default:
175
- $result = array('error' => 'Wrong action provided. Please try again.');
176
- break;
177
- }
178
- } else {
179
- $result = array('error' => 'User not found.');
180
- }
181
-
182
- if(is_wp_error($result)){
183
- $result = array('error' => $result->get_error_message());
184
- }
185
-
186
- $return[$user] = $result;
187
- }
188
- }
189
-
190
- return $return;
191
-
192
- }
193
-
194
- //Check if user is the only one admin on the site
195
- function last_admin($user_obj){
196
- global $wpdb;
197
- $field = $wpdb->prefix."capabilities";
198
- $capabilities = array_map('strtolower',array_keys($user_obj->$field));
199
- $result = count_users();
200
- if(in_array('administrator',$capabilities)){
201
-
202
- if(!function_exists('count_users')){
203
- include_once (ABSPATH . WPINC. '/user.php');
204
- }
205
-
206
- $result = count_users();
207
- if($result['avail_roles']['administrator'] == 1){
208
- return true;
209
- }
210
- }
211
- return false;
212
- }
213
-
214
- }
215
  ?>
1
+ <?php
2
+ /*************************************************************
3
+ *
4
+ * user.class.php
5
+ *
6
+ * Add Users
7
+ *
8
+ *
9
+ * Copyright (c) 2011 Prelovac Media
10
+ * www.prelovac.com
11
+ **************************************************************/
12
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "user.class.php"):
13
+ exit;
14
+ endif;
15
+ class MMB_User extends MMB_Core
16
+ {
17
+ function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ function get_users($args){
23
+ global $wpdb;
24
+
25
+ //$args: $user_roles;
26
+ if(empty($args))
27
+ return false;
28
+
29
+ extract($args);
30
+
31
+ $userlevels = array();
32
+ $level_strings = array();
33
+ foreach($user_roles as $user_role){
34
+ switch(strtolower($user_role)){
35
+ case 'subscriber' : $userlevels[] = 0; $level_strings[] = $user_role; break;
36
+ case 'contributor' : $userlevels[] = 1; $level_strings[] = $user_role; break;
37
+ case 'author' : $userlevels[] = 2; $level_strings[] = $user_role; break;
38
+ case 'editor' : $userlevels[] = 7; $level_strings[] = $user_role; break;
39
+ case 'administrator' : $userlevels[] = 10; $level_strings[] = $user_role; break;
40
+ default: break;
41
+ }
42
+ }
43
+
44
+ $users = array();
45
+ $userlevel_qry = "('".implode("','",$userlevels)."')";
46
+ $userlevel_fallback_qry = "('%".implode("%','%",$level_strings)."%')";
47
+ $field = $wpdb->prefix."capabilities";
48
+
49
+ $user_metas = $wpdb->get_results("SELECT * from $wpdb->usermeta WHERE meta_key = '$field' AND meta_value IN $userlevel_fallback_qry");
50
+ if($user_metas == false || empty($user_metas)){
51
+ $user_metas = $wpdb->get_results("SELECT * from $wpdb->usermeta WHERE meta_key = 'wp_user_level' AND meta_value IN $userlevel_qry");
52
+ }
53
+
54
+ $include = array();
55
+ if(is_array($user_metas) && !empty($user_metas)){
56
+ foreach($user_metas as $user_meta){
57
+ $include[] = $user_meta->user_id;
58
+ }
59
+ }
60
+
61
+ $args = array();
62
+ $args['include'] = $include;
63
+ $args['fields'] = 'all_with_meta';
64
+ $temp_users = get_users($args);
65
+ $user = array();
66
+ foreach ((array)$temp_users as $temp){
67
+ $user['user_id'] = $temp->ID;
68
+ $user['user_login'] = $temp->user_login;
69
+ $user['wp_capabilities'] = array_keys($temp->$field);
70
+ $users[] = $user;
71
+ }
72
+
73
+ return array('users' => $users);
74
+ }
75
+
76
+ function add_user($args)
77
+ {
78
+
79
+ if(!function_exists('username_exists') || !function_exists('email_exists'))
80
+ include_once(ABSPATH . WPINC . '/registration.php');
81
+
82
+ if(username_exists($args['user_login']))
83
+ return array('error' => 'Username already exists');
84
+
85
+ if (email_exists($args['user_email']))
86
+ return array('error' => 'Email already exists');
87
+
88
+ if(!function_exists('wp_insert_user'))
89
+ include_once (ABSPATH . 'wp-admin/includes/user.php');
90
+
91
+ $user_id = wp_insert_user($args);
92
+
93
+ if($user_id){
94
+
95
+ if($args['email_notify']){
96
+ //require_once ABSPATH . WPINC . '/pluggable.php';
97
+ wp_new_user_notification($user_id, $args['user_pass']);
98
+ }
99
+ return $user_id;
100
+ }else{
101
+ return array('error' => 'User not added. Please try again.');
102
+ }
103
+
104
+ }
105
+
106
+ function edit_users($args){
107
+
108
+ if(empty($args))
109
+ return false;
110
+ if(!function_exists('get_user_to_edit'))
111
+ include_once (ABSPATH . 'wp-admin/includes/user.php');
112
+ if(!function_exists('wp_update_user'))
113
+ include_once (ABSPATH . WPINC.'/user.php');
114
+
115
+ extract($args);
116
+ //$args: $users, $new_role, $new_password, $user_edit_action
117
+
118
+ $return = array();
119
+ if(count($users)){
120
+ foreach($users as $user){
121
+ $result = '';
122
+ $user_obj = $this->mmb_get_user_info( $user );
123
+ if($user_obj != false){
124
+ switch($user_edit_action){
125
+ case 'change-password':
126
+ if($new_password){
127
+ $user_data = array();
128
+ $userdata['user_pass'] = $new_password;
129
+ $userdata['ID'] = $user_obj->ID;
130
+ $result = wp_update_user($userdata);
131
+ } else {
132
+ $result = array('error' => 'No password provided.');
133
+ }
134
+ break;
135
+ case 'change-role':
136
+ if($new_role){
137
+ if($user != $username){
138
+ if(!$this->last_admin($user_obj)){
139
+ $user_data = array();
140
+ $userdata['ID'] = $user_obj->ID;
141
+ $userdata['role'] = strtolower($new_role);
142
+ $result = wp_update_user($userdata);
143
+ } else {
144
+ $result = array('error' => 'Cannot change role to the only one left admin user.');
145
+ }
146
+ } else {
147
+ $result = array('error' => 'Cannot change role to user assigned for ManageWP.');
148
+ }
149
+ } else {
150
+ $result = array('error' => 'No role provided.');
151
+ }
152
+ break;
153
+ case 'delete-user':
154
+ if($user != $username){
155
+ if(!$this->last_admin($user_obj)){
156
+ if($reassign_user){
157
+ $to_user = $this->mmb_get_user_info( $reassign_user );
158
+ if($to_user != false){
159
+ $result = wp_delete_user($user_obj->ID, $to_user->ID);
160
+ } else {
161
+ $result = array('error' => 'User not deleted. User to reassign posts doesn\'t exist.');
162
+ }
163
+ } else {
164
+ $result = wp_delete_user($user_obj->ID);
165
+ }
166
+ } else {
167
+ $result = array('error' => 'Cannot delete the only one left admin user.');
168
+ }
169
+ } else {
170
+ $result = array('error' => 'Cannot delete user assigned for ManageWP.');
171
+ }
172
+
173
+ break;
174
+ default:
175
+ $result = array('error' => 'Wrong action provided. Please try again.');
176
+ break;
177
+ }
178
+ } else {
179
+ $result = array('error' => 'User not found.');
180
+ }
181
+
182
+ if(is_wp_error($result)){
183
+ $result = array('error' => $result->get_error_message());
184
+ }
185
+
186
+ $return[$user] = $result;
187
+ }
188
+ }
189
+
190
+ return $return;
191
+
192
+ }
193
+
194
+ //Check if user is the only one admin on the site
195
+ function last_admin($user_obj){
196
+ global $wpdb;
197
+ $field = $wpdb->prefix."capabilities";
198
+ $capabilities = array_map('strtolower',array_keys($user_obj->$field));
199
+ $result = count_users();
200
+ if(in_array('administrator',$capabilities)){
201
+
202
+ if(!function_exists('count_users')){
203
+ include_once (ABSPATH . WPINC. '/user.php');
204
+ }
205
+
206
+ $result = count_users();
207
+ if($result['avail_roles']['administrator'] == 1){
208
+ return true;
209
+ }
210
+ }
211
+ return false;
212
+ }
213
+
214
+ }
215
  ?>
version CHANGED
@@ -1 +1 @@
1
- 3.9.19
1
+ 3.9.20
widget.class.php CHANGED
@@ -1,54 +1,54 @@
1
- <?php
2
- /**
3
- * ManageWP_Widget Class
4
- */
5
- if(basename($_SERVER['SCRIPT_FILENAME']) == "widget.class.php"):
6
- exit;
7
- endif;
8
- class ManageWP_Widget extends WP_Widget {
9
-
10
-
11
- /** constructor -- name this the same as the class above */
12
- function ManageWP_Widget() {
13
- parent::WP_Widget(false, $name = 'ManageWP', array('description' => 'ManageWP widget.'));
14
- }
15
-
16
- /** @see WP_Widget::widget -- do not rename this */
17
- function widget($args, $instance) {
18
- extract( $args );
19
- $instance['title'] = 'ManageWP';
20
- $instance['message'] = 'We are happily using <a href="http://managewp.com" target="_blank">ManageWP</a>';
21
- $title = apply_filters('widget_title', $instance['title']);
22
- $message = $instance['message'];
23
- ?>
24
- <?php echo $before_widget; ?>
25
- <?php if ( $title )
26
- echo $before_title . $title . $after_title; ?>
27
- <ul>
28
- <li><?php echo $message; ?></li>
29
- </ul>
30
- <?php echo $after_widget; ?>
31
- <?php
32
- }
33
-
34
- /** @see WP_Widget::form -- do not rename this */
35
- function form($instance) {
36
- $title = 'ManageWP';
37
- $message = 'We are happily using <a href="http://managewp.com" target="_blank">ManageWP</a>';
38
- echo '<p>'.$message.'</p>';
39
- }
40
-
41
-
42
- } // end class example_widget
43
-
44
- $mwp_worker_brand = get_option("mwp_worker_brand");
45
- $worker_brand = 0;
46
- if(is_array($mwp_worker_brand)){
47
- if($mwp_worker_brand['name'] || $mwp_worker_brand['desc'] || $mwp_worker_brand['author'] || $mwp_worker_brand['author_url']){
48
- $worker_brand= 1;
49
- }
50
- }
51
- if(!$worker_brand){
52
- add_action('widgets_init', create_function('', 'return register_widget("ManageWP_Widget");'));
53
- }
54
  ?>
1
+ <?php
2
+ /**
3
+ * ManageWP_Widget Class
4
+ */
5
+ if(basename($_SERVER['SCRIPT_FILENAME']) == "widget.class.php"):
6
+ exit;
7
+ endif;
8
+ class ManageWP_Widget extends WP_Widget {
9
+
10
+
11
+ /** constructor -- name this the same as the class above */
12
+ function ManageWP_Widget() {
13
+ parent::WP_Widget(false, $name = 'ManageWP', array('description' => 'ManageWP widget.'));
14
+ }
15
+
16
+ /** @see WP_Widget::widget -- do not rename this */
17
+ function widget($args, $instance) {
18
+ extract( $args );
19
+ $instance['title'] = 'ManageWP';
20
+ $instance['message'] = 'We are happily using <a href="http://managewp.com" target="_blank">ManageWP</a>';
21
+ $title = apply_filters('widget_title', $instance['title']);
22
+ $message = $instance['message'];
23
+ ?>
24
+ <?php echo $before_widget; ?>
25
+ <?php if ( $title )
26
+ echo $before_title . $title . $after_title; ?>
27
+ <ul>
28
+ <li><?php echo $message; ?></li>
29
+ </ul>
30
+ <?php echo $after_widget; ?>
31
+ <?php
32
+ }
33
+
34
+ /** @see WP_Widget::form -- do not rename this */
35
+ function form($instance) {
36
+ $title = 'ManageWP';
37
+ $message = 'We are happily using <a href="http://managewp.com" target="_blank">ManageWP</a>';
38
+ echo '<p>'.$message.'</p>';
39
+ }
40
+
41
+
42
+ } // end class example_widget
43
+
44
+ $mwp_worker_brand = get_option("mwp_worker_brand");
45
+ $worker_brand = 0;
46
+ if(is_array($mwp_worker_brand)){
47
+ if($mwp_worker_brand['name'] || $mwp_worker_brand['desc'] || $mwp_worker_brand['author'] || $mwp_worker_brand['author_url']){
48
+ $worker_brand= 1;
49
+ }
50
+ }
51
+ if(!$worker_brand){
52
+ add_action('widgets_init', create_function('', 'return register_widget("ManageWP_Widget");'));
53
+ }
54
  ?>