InfiniteWP Client - Version 1.2.6

Version Description

  • Fix: Bug fixes
Download this release

Release Info

Developer infinitewp
Plugin Icon 128x128 InfiniteWP Client
Version 1.2.6
Comparing to
See all releases

Code changes from version 1.2.5 to 1.2.6

Files changed (5) hide show
  1. addons/post_links/post.class.php +131 -127
  2. backup.class.php +2806 -2806
  3. init.php +2 -2
  4. lib/amazon_s3/sdk.class.php +1556 -1556
  5. readme.txt +4 -1
addons/post_links/post.class.php CHANGED
@@ -109,133 +109,137 @@ class IWP_MMB_Post extends IWP_MMB_Core
109
  if ($match_count > 0) {
110
  $attachments = array();
111
  $post_content = $post_data['post_content'];
112
-
113
- foreach ($get_urls as $get_url_k => $get_url) {
114
- // unset url in attachment array
115
- foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
116
- $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
117
- if (preg_match($match_patt_url, $get_url[4])) {
118
- unset($post_atta_img[$atta_url_k]);
119
- }
120
- }
121
- $pic_from_other_site = $get_urls[$get_url_k][4];
122
- /* if(strpos($pic_from_other_site,'exammple.com') === false){
123
- continue;
124
- }*/
125
-
126
- if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
127
- if ($get_url[1] != '') {
128
- // change src url
129
- $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
130
-
131
- $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
132
- $s_mmb_rp = $s_img_atta[0];
133
- $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
134
- // change attachment url
135
- if (preg_match('/attachment_id/i', $get_url[2])) {
136
- $iwp_mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
137
- $iwp_mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
138
- $post_content = preg_replace($iwp_mmb_mp, $iwp_mmb_rp, $post_content);
139
- }
140
- }
141
- continue;
142
- }
143
-
144
- $no_thumb = '';
145
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
146
- $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
147
- } else {
148
- $no_thumb = $get_url[4];
149
- }
150
-
151
- if(isset($upload['error']) && !empty($upload['error'])){
152
- return array('error' => $upload['error']);
153
- }
154
- $file_name = basename($no_thumb);
155
- $tmp_file = download_url($no_thumb);
156
-
157
- if(is_wp_error($tmp_file)){
158
- return array('error' => $tmp_file->get_error_message());
159
- }
160
-
161
- $attach_upload['url'] = $upload['url'] . '/' . $file_name;
162
- $attach_upload['path'] = $upload['path'] . '/' . $file_name;
163
- $renamed = @rename($tmp_file, $attach_upload['path']);
164
- if ($renamed === true) {
165
- $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
166
- $replace_pattern = $attach_upload['url'];
167
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
168
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
169
- $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])) . '/';
170
- $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
171
- }
172
-
173
- $attachment = array(
174
- 'post_title' => $file_name,
175
- 'post_content' => '',
176
- 'post_type' => 'attachment',
177
- //'post_parent' => $post_id,
178
- 'post_mime_type' => 'image/' . $get_url[5],
179
- 'guid' => $attach_upload['url']
180
- );
181
-
182
- // Save the data
183
-
184
- $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
185
-
186
- $attachments[$attach_id] = 0;
187
-
188
- // featured image
189
- if ($post_featured_img != '') {
190
- $feat_img_url = '';
191
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
192
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
193
- } else {
194
- $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
195
- }
196
- $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
197
- if (preg_match($m_feat_url, $get_url[4])) {
198
- $post_featured_img = '';
199
- $attachments[$attach_id] = $attach_id;
200
- }
201
- }
202
-
203
- // set $get_urls value[6] - parent atta_id
204
- foreach ($get_urls as $url_k => $url_v) {
205
- if ($get_url_k != $url_k) {
206
- $s_get_url = '';
207
- if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
208
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
209
- } else {
210
- $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
211
- }
212
- $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
213
- if (preg_match($m_patt_url, $get_url[4])) {
214
- array_push($get_urls[$url_k], $attach_id);
215
- }
216
- }
217
- }
218
-
219
-
220
- $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
221
- wp_update_attachment_metadata($attach_id, $some_data);
222
-
223
-
224
- //changing href of a tag
225
- if ($get_url[1] != '') {
226
- $iwp_mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
227
- if (preg_match('/attachment_id/i', $get_url[2])) {
228
- $iwp_mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
229
- $post_content = preg_replace($iwp_mmb_mp, $iwp_mmb_rp, $post_content);
230
- }
231
- }
232
- } else {
233
- @unlink($tmp_file);
234
- return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
235
-
236
- }
237
- @unlink($tmp_file);
238
- }
 
 
 
 
239
 
240
 
241
  $post_data['post_content'] = $post_content;
109
  if ($match_count > 0) {
110
  $attachments = array();
111
  $post_content = $post_data['post_content'];
112
+
113
+ if(!empty($get_urls) && is_array($get_urls)){
114
+ foreach ($get_urls as $get_url_k => $get_url) {
115
+ // unset url in attachment array
116
+ if(!empty($post_atta_img) && is_array($post_atta_img)){
117
+ foreach ($post_atta_img as $atta_url_k => $atta_url_v) {
118
+ $match_patt_url = '/' . str_replace($rep, $with, substr($atta_url_v['src'], 0, strrpos($atta_url_v['src'], '.'))) . '/';
119
+ if (preg_match($match_patt_url, $get_url[4])) {
120
+ unset($post_atta_img[$atta_url_k]);
121
+ }
122
+ }
123
+ }
124
+ $pic_from_other_site = $get_urls[$get_url_k][4];
125
+ /* if(strpos($pic_from_other_site,'exammple.com') === false){
126
+ continue;
127
+ }*/
128
+
129
+ if (isset($get_urls[$get_url_k][6])) { // url have parent, don't download this url
130
+ if ($get_url[1] != '') {
131
+ // change src url
132
+ $s_mmb_mp = '/' . str_replace($rep, $with, $get_url[4]) . '/';
133
+
134
+ $s_img_atta = wp_get_attachment_image_src($get_urls[$get_url_k][6]);
135
+ $s_mmb_rp = $s_img_atta[0];
136
+ $post_content = preg_replace($s_mmb_mp, $s_mmb_rp, $post_content);
137
+ // change attachment url
138
+ if (preg_match('/attachment_id/i', $get_url[2])) {
139
+ $iwp_mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
140
+ $iwp_mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $get_urls[$get_url_k][6];
141
+ $post_content = preg_replace($iwp_mmb_mp, $iwp_mmb_rp, $post_content);
142
+ }
143
+ }
144
+ continue;
145
+ }
146
+
147
+ $no_thumb = '';
148
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
149
+ $no_thumb = preg_replace('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', '.' . $get_url[5], $get_url[4]);
150
+ } else {
151
+ $no_thumb = $get_url[4];
152
+ }
153
+
154
+ if(isset($upload['error']) && !empty($upload['error'])){
155
+ return array('error' => $upload['error']);
156
+ }
157
+ $file_name = basename($no_thumb);
158
+ $tmp_file = download_url($no_thumb);
159
+
160
+ if(is_wp_error($tmp_file)){
161
+ return array('error' => $tmp_file->get_error_message());
162
+ }
163
+
164
+ $attach_upload['url'] = $upload['url'] . '/' . $file_name;
165
+ $attach_upload['path'] = $upload['path'] . '/' . $file_name;
166
+ $renamed = @rename($tmp_file, $attach_upload['path']);
167
+ if ($renamed === true) {
168
+ $match_pattern = '/' . str_replace($rep, $with, $get_url[4]) . '/';
169
+ $replace_pattern = $attach_upload['url'];
170
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
171
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $get_url[4])) {
172
+ $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])) . '/';
173
+ $post_content = preg_replace($match_pattern, $replace_pattern, $post_content);
174
+ }
175
+
176
+ $attachment = array(
177
+ 'post_title' => $file_name,
178
+ 'post_content' => '',
179
+ 'post_type' => 'attachment',
180
+ //'post_parent' => $post_id,
181
+ 'post_mime_type' => 'image/' . $get_url[5],
182
+ 'guid' => $attach_upload['url']
183
+ );
184
+
185
+ // Save the data
186
+
187
+ $attach_id = wp_insert_attachment($attachment, $attach_upload['path']);
188
+
189
+ $attachments[$attach_id] = 0;
190
+
191
+ // featured image
192
+ if ($post_featured_img != '') {
193
+ $feat_img_url = '';
194
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $post_featured_img)) {
195
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.') - 8);
196
+ } else {
197
+ $feat_img_url = substr($post_featured_img, 0, strrpos($post_featured_img, '.'));
198
+ }
199
+ $m_feat_url = '/' . str_replace($rep, $with, $feat_img_url) . '/';
200
+ if (preg_match($m_feat_url, $get_url[4])) {
201
+ $post_featured_img = '';
202
+ $attachments[$attach_id] = $attach_id;
203
+ }
204
+ }
205
+
206
+ // set $get_urls value[6] - parent atta_id
207
+ foreach ($get_urls as $url_k => $url_v) {
208
+ if ($get_url_k != $url_k) {
209
+ $s_get_url = '';
210
+ if (preg_match('/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $url_v[4])) {
211
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.') - 8);
212
+ } else {
213
+ $s_get_url = substr($url_v[4], 0, strrpos($url_v[4], '.'));
214
+ }
215
+ $m_patt_url = '/' . str_replace($rep, $with, $s_get_url) . '/';
216
+ if (preg_match($m_patt_url, $get_url[4])) {
217
+ array_push($get_urls[$url_k], $attach_id);
218
+ }
219
+ }
220
+ }
221
+
222
+
223
+ $some_data = wp_generate_attachment_metadata($attach_id, $attach_upload['path']);
224
+ wp_update_attachment_metadata($attach_id, $some_data);
225
+
226
+
227
+ //changing href of a tag
228
+ if ($get_url[1] != '') {
229
+ $iwp_mmb_mp = '/' . str_replace($rep, $with, $get_url[2]) . '/';
230
+ if (preg_match('/attachment_id/i', $get_url[2])) {
231
+ $iwp_mmb_rp = get_bloginfo('wpurl') . '/?attachment_id=' . $attach_id;
232
+ $post_content = preg_replace($iwp_mmb_mp, $iwp_mmb_rp, $post_content);
233
+ }
234
+ }
235
+ } else {
236
+ @unlink($tmp_file);
237
+ return array('error' => "Cannot create attachment file in ".$attach_upload['path']." Please set correct permissions.");
238
+
239
+ }
240
+ @unlink($tmp_file);
241
+ }
242
+ }
243
 
244
 
245
  $post_data['post_content'] = $post_content;
backup.class.php CHANGED
@@ -1,2807 +1,2807 @@
1
- <?php
2
- /************************************************************
3
- * This plugin was modified by Revmakx *
4
- * Copyright (c) 2012 Revmakx *
5
- * www.revmakx.com *
6
- * *
7
- ************************************************************/
8
- /*************************************************************
9
- *
10
- * backup.class.php
11
- *
12
- * Manage Backups
13
- *
14
- *
15
- * Copyright (c) 2011 Prelovac Media
16
- * www.prelovac.com
17
- **************************************************************/
18
- define('IWP_BACKUP_DIR', WP_CONTENT_DIR . '/infinitewp/backups');
19
- define('IWP_DB_DIR', IWP_BACKUP_DIR . '/iwp_db');
20
-
21
- $zip_errors = array(
22
- 'No error',
23
- 'No error',
24
- 'Unexpected end of zip file',
25
- 'A generic error in the zipfile format was detected',
26
- 'zip was unable to allocate itself memory',
27
- 'A severe error in the zipfile format was detected',
28
- 'Entry too large to be split with zipsplit',
29
- 'Invalid comment format',
30
- 'zip -T failed or out of memory',
31
- 'The user aborted zip prematurely',
32
- 'zip encountered an error while using a temp file. Please check if this domain\'s account has enough disk space.',
33
- 'Read or seek error',
34
- 'zip has nothing to do',
35
- 'Missing or empty zip file',
36
- 'Error writing to a file. Please check if this domain\'s account has enough disk space.',
37
- 'zip was unable to create a file to write to',
38
- 'bad command line parameters',
39
- 'no error',
40
- 'zip could not open a specified file to read'
41
- );
42
- $unzip_errors = array(
43
- 'No error',
44
- 'One or more warning errors were encountered, but processing completed successfully anyway',
45
- 'A generic error in the zipfile format was detected',
46
- 'A severe error in the zipfile format was detected.',
47
- 'unzip was unable to allocate itself memory.',
48
- 'unzip was unable to allocate memory, or encountered an encryption error',
49
- 'unzip was unable to allocate memory during decompression to disk',
50
- 'unzip was unable allocate memory during in-memory decompression',
51
- 'unused',
52
- 'The specified zipfiles were not found',
53
- 'Bad command line parameters',
54
- 'No matching files were found',
55
- 50 => 'The disk is (or was) full during extraction',
56
- 51 => 'The end of the ZIP archive was encountered prematurely.',
57
- 80 => 'The user aborted unzip prematurely.',
58
- 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
59
- 82 => 'No files were found due to bad decryption password(s)'
60
- );
61
-
62
-
63
- class IWP_MMB_Backup extends IWP_MMB_Core
64
- {
65
- var $site_name;
66
- var $statuses;
67
- var $tasks;
68
- var $s3;
69
- var $ftp;
70
- var $dropbox;
71
- function __construct()
72
- {
73
- parent::__construct();
74
- $this->site_name = str_replace(array(
75
- "_",
76
- "/",
77
- "~"
78
- ), array(
79
- "",
80
- "-",
81
- "-"
82
- ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
83
- $this->statuses = array(
84
- 'db_dump' => 1,
85
- 'db_zip' => 2,
86
- 'files_zip' => 3,
87
- 'finished' => 100
88
- );
89
- $this->tasks = get_option('iwp_client_backup_tasks');
90
- }
91
- function set_memory()
92
- {
93
- $changed = array('execution_time' => 0, 'memory_limit' => 0);
94
- @ignore_user_abort(true);
95
- $memory_limit = trim(ini_get('memory_limit'));
96
- $last = strtolower(substr($memory_limit, -1));
97
-
98
- if($last == 'g')
99
- $memory_limit = ((int) $memory_limit)*1024;
100
- else if($last == 'm')
101
- $memory_limit = (int) $memory_limit;
102
- if($last == 'k')
103
- $memory_limit = ((int) $memory_limit)/1024;
104
-
105
- if ( $memory_limit < 384 ) {
106
- @ini_set('memory_limit', '384M');
107
- $changed['memory_limit'] = 1;
108
- }
109
-
110
- if ( (int) @ini_get('max_execution_time') < 1200 ) {
111
- @ini_set('max_execution_time', 1200);//twenty minutes
112
- @set_time_limit(1200);
113
- $changed['execution_time'] = 1;
114
- }
115
-
116
- return $changed;
117
-
118
- }
119
- function get_backup_settings()
120
- {
121
- $backup_settings = get_option('iwp_client_backup_tasks');
122
- if (!empty($backup_settings))
123
- return $backup_settings;
124
- else
125
- return false;
126
- }
127
-
128
- function set_backup_task($params)
129
- {
130
- //$params => [$task_name, $args, $error]
131
- if (!empty($params)) {
132
-
133
- //Make sure backup cron job is set
134
- if (!wp_next_scheduled('iwp_client_backup_tasks')) {
135
- wp_schedule_event( time(), 'tenminutes', 'iwp_client_backup_tasks' );
136
- }
137
-
138
- extract($params);
139
-
140
- //$before = $this->get_backup_settings();
141
- $before = $this->tasks;
142
- if (!$before || empty($before))
143
- $before = array();
144
-
145
- if (isset($args['remove'])) {
146
- unset($before[$task_name]);
147
- $return = array(
148
- 'removed' => true
149
- );
150
- } else {
151
-
152
- if (is_array($params['account_info'])) { //only if sends from IWP Admin Panel first time(secure data)
153
- $args['account_info'] = $account_info;
154
- }
155
-
156
- $before[$task_name]['task_args'] = $args;
157
- //$before[$task_name]['task_args'] = $task_name;
158
-
159
- /*if (strlen($args['schedule']))
160
- $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);*///to WP cron
161
- $before[$task_name]['task_args']['task_name'] = $task_name;
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 (isset($time) && $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'] = (isset($time) && $time) ? $time : time();
180
- //}
181
- if (isset($time) && $time) { //This will occur for schedule runtask.
182
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
183
- }else{
184
- if($task_name == 'Backup Now')
185
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = time();
186
- }
187
-
188
- $this->update_tasks($before);
189
- //update_option('iwp_client_backup_tasks', $before);
190
-
191
- if ($task_name == 'Backup Now') {
192
- $result = $this->backup($args, $task_name);
193
- $backup_settings = $this->tasks;
194
-
195
- if (is_array($result) && array_key_exists('error', $result)) {
196
- $return = $result;
197
- } else {
198
- $return = $backup_settings[$task_name];
199
- }
200
- }
201
- return $return;
202
- }
203
-
204
-
205
-
206
- return false;
207
- }
208
-
209
- //Cron check
210
- function check_backup_tasks()
211
- {
212
-
213
- $this->check_cron_remove();
214
-
215
- $settings = $this->tasks;
216
- if (is_array($settings) && !empty($settings)) {
217
- foreach ($settings as $task_name => $setting) {
218
-
219
- if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
220
- //if ($setting['task_args']['next'] && $_GET['force_backup']) {
221
- if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
222
- //Check orphan task
223
- $check_data = array(
224
- 'task_name' => $task_name,
225
- 'task_id' => $setting['task_args']['task_id'],
226
- 'site_key' => $setting['task_args']['site_key']
227
- );
228
-
229
- $check = $this->validate_task($check_data, $setting['task_args']['url']);
230
-
231
- }
232
-
233
- $update = array(
234
- 'task_name' => $task_name,
235
- 'args' => $settings[$task_name]['task_args']
236
- );
237
-
238
-
239
- if($check != 'paused'){
240
- $update['time'] = time();
241
- }
242
-
243
- //Update task with next schedule
244
- $this->set_backup_task($update);
245
-
246
- if($check == 'paused'){
247
- continue;
248
- }
249
-
250
-
251
- $result = $this->backup($setting['task_args'], $task_name);
252
- $error = '';
253
- if (is_array($result) && array_key_exists('error', $result)) {
254
- $error = $result;
255
- $this->set_backup_task(array(
256
- 'task_name' => $task_name,
257
- 'args' => $settings[$task_name]['task_args'],
258
- 'error' => $error
259
- ));
260
- } else {
261
- $error = '';
262
- }
263
- break; //Only one backup per cron
264
- }
265
- }
266
- }
267
-
268
- }
269
-
270
-
271
- function task_now($task_name){
272
-
273
- $settings = $this->tasks;
274
- if(!array_key_exists($task_name,$settings)){
275
- return array('error' => $task_name." does not exist.");
276
- } else {
277
- $setting = $settings[$task_name];
278
- }
279
-
280
- $this->set_backup_task(array(
281
- 'task_name' => $task_name,
282
- 'args' => $settings[$task_name]['task_args'],
283
- 'time' => time()
284
- ));
285
-
286
- //Run backup
287
- $result = $this->backup($setting['task_args'], $task_name);
288
-
289
- //Check for error
290
- if (is_array($result) && array_key_exists('error', $result)) {
291
- $this->set_backup_task(array(
292
- 'task_name' => $task_name,
293
- 'args' => $settings[$task_name]['task_args'],
294
- 'error' => $result['error']
295
- ));
296
- return $result;
297
- } else {
298
- return $this->get_backup_stats();
299
- }
300
-
301
- }
302
-
303
- function delete_task_now($task_name){
304
- $tasks = $this->tasks;
305
- unset($tasks[$task_name]);
306
- $this->update_tasks($tasks);
307
- $this->cleanup();
308
-
309
- return $task_name;
310
-
311
- }
312
-
313
-
314
- /*
315
- * If Task Name not set then it's manual backup
316
- * Backup args:
317
- * type -> db, full
318
- * what -> daily, weekly, monthly
319
- * account_info -> ftp, amazons3, dropbox
320
- * exclude-> array of paths to exclude from backup
321
- */
322
-
323
- function backup($args, $task_name = false)
324
- {
325
- if (!$args || empty($args))
326
- return false;
327
-
328
- extract($args); //extract settings
329
-
330
- //$adminHistoryID - admin panel history ID for backup task.
331
-
332
-
333
- //Try increase memory limit and execution time
334
- $this->set_memory();
335
-
336
- //Remove old backup(s)
337
- $removed = $this->remove_old_backups($task_name);
338
- if (is_array($removed) && isset($removed['error'])) {
339
- //$error_message = $removed['error'];
340
- return $removed;
341
- }
342
-
343
- $new_file_path = IWP_BACKUP_DIR;
344
-
345
- if (!file_exists($new_file_path)) {
346
- if (!mkdir($new_file_path, 0755, true))
347
- return array(
348
- 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
349
- );
350
- }
351
-
352
- @file_put_contents($new_file_path . '/index.php', ''); //safe
353
-
354
- //Prepare .zip file name
355
- $hash = md5(time());
356
- $label = $type ? $type : 'manual';
357
- $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
358
- $backup_url = WP_CONTENT_URL . '/infinitewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
359
-
360
- //Optimize tables?
361
- if (isset($optimize_tables) && !empty($optimize_tables)) {
362
- $this->optimize_tables();
363
- }
364
-
365
- //What to backup - db or full?
366
- if (trim($what) == 'db') {
367
- //Take database backup
368
- $this->update_status($task_name, 'db_dump');
369
- $GLOBALS['fail_safe_db'] = $this->tasks[$task_name]['task_args']['fail_safe_db'];
370
-
371
- $db_result = $this->backup_db();
372
- if ($db_result == false) {
373
- return array(
374
- 'error' => 'Failed to backup database.'
375
- );
376
- } else if (is_array($db_result) && isset($db_result['error'])) {
377
- return array(
378
- 'error' => $db_result['error']
379
- );
380
- } else {
381
- $this->update_status($task_name, 'db_dump', true);
382
- $this->update_status($task_name, 'db_zip');
383
-
384
- /*zip_backup_db*/
385
- $fail_safe_files = $this->tasks[$task_name]['task_args']['fail_safe_files'];
386
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
387
-
388
- if($fail_safe_files){
389
- $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
390
- }
391
- else{
392
- $comp_level = $disable_comp ? '-0' : '-1';
393
- chdir(IWP_BACKUP_DIR);
394
- $zip = $this->get_zip();
395
- $command = "$zip -q -r $comp_level $backup_file 'iwp_db'";
396
- iwp_mmb_print_flush('DB ZIP CMD: Start');
397
- ob_start();
398
- $result = $this->iwp_mmb_exec($command);
399
- ob_get_clean();
400
- iwp_mmb_print_flush('DB ZIP CMD: End');
401
- /*zip_backup_db */
402
- if(!$result){
403
- $zip_archive_db_result = false;
404
- if (class_exists("ZipArchive")) {
405
- $this->_log("DB zip, fallback to ZipArchive");
406
- iwp_mmb_print_flush('DB ZIP Archive: Start');
407
- $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
408
- iwp_mmb_print_flush('DB ZIP Archive: End');
409
- }
410
-
411
- if (!$zip_archive_db_result) {
412
- $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
413
- }
414
- }
415
- }
416
-
417
- @unlink($db_result);
418
- @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
419
- @rmdir(IWP_DB_DIR);
420
- /*if (!$result) {
421
- return array(
422
- 'error' => 'Failed to zip database.'
423
- );
424
- }*///commented because of zipArchive
425
- $this->update_status($task_name, 'db_zip', true);
426
- }
427
- } elseif (trim($what) == 'full') {
428
- $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
429
- if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
430
- return array(
431
- 'error' => $content_backup['error']
432
- );
433
- }
434
- }
435
-
436
- //Update backup info
437
- if ($task_name) {
438
- //backup task (scheduled)
439
- $backup_settings = $this->tasks;
440
- $paths = array();
441
- $size = round(filesize($backup_file) / 1024, 2);
442
-
443
- if ($size > 1000) {
444
- $paths['size'] = round($size / 1024, 2) . " MB";//Modified by IWP //Mb => MB
445
- } else {
446
- $paths['size'] = $size . 'KB';//Modified by IWP //Kb => KB
447
- }
448
-
449
- $paths['backup_name'] = $backup_settings[$task_name]['task_args']['backup_name'];
450
-
451
- if ($task_name != 'Backup Now') {
452
- if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
453
- $paths['server'] = array(
454
- 'file_path' => $backup_file,
455
- 'file_url' => $backup_url
456
- );
457
- }
458
- } else {
459
- $paths['server'] = array(
460
- 'file_path' => $backup_file,
461
- 'file_url' => $backup_url
462
- );
463
- }
464
-
465
-
466
- if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_ftp'])) {
467
- $paths['ftp'] = basename($backup_url);
468
- }
469
-
470
- if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_amazon_s3'])) {
471
- $paths['amazons3'] = basename($backup_url);
472
- }
473
-
474
- if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_dropbox'])) {
475
- $paths['dropbox'] = basename($backup_url);
476
- }
477
-
478
- if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_email'])) {
479
- $paths['email'] = basename($backup_url);
480
- }
481
-
482
- $temp = $backup_settings[$task_name]['task_results'];
483
- $temp = @array_values($temp);
484
- $paths['time'] = time();
485
-
486
-
487
- //if ($task_name != 'Backup Now') {
488
- $paths['backhack_status'] = $temp[count($temp) - 1]['backhack_status'];
489
- //$paths['status'] = $temp[count($temp) - 1]['status'];
490
- $temp[count($temp) - 1] = $paths;
491
-
492
- /*
493
- } else {
494
- $temp[count($temp)] = $paths;
495
- }
496
- */
497
-
498
- $backup_settings[$task_name]['task_results'] = $temp;
499
- $this->update_tasks($backup_settings);
500
- //update_option('iwp_client_backup_tasks', $backup_settings);
501
- }
502
-
503
-
504
- if ($task_name != 'Backup Now') {
505
-
506
- if (isset($account_info['iwp_ftp']) && !empty($account_info['iwp_ftp'])) {
507
- $this->update_status($task_name, 'ftp');
508
- $account_info['iwp_ftp']['backup_file'] = $backup_file;
509
- iwp_mmb_print_flush('FTP upload: Start');
510
- $ftp_result = $this->ftp_backup($account_info['iwp_ftp']);
511
- iwp_mmb_print_flush('FTP upload: End');
512
- if ($ftp_result !== true && $del_host_file) {
513
- @unlink($backup_file);
514
- }
515
-
516
- if (is_array($ftp_result) && isset($ftp_result['error'])) {
517
- return $ftp_result;
518
- }
519
- $this->wpdb_reconnect();
520
- $this->update_status($task_name, 'ftp', true);
521
- }
522
-
523
- if (isset($account_info['iwp_amazon_s3']) && !empty($account_info['iwp_amazon_s3'])) {
524
- $this->update_status($task_name, 's3');
525
- $account_info['iwp_amazon_s3']['backup_file'] = $backup_file;
526
- iwp_mmb_print_flush('Amazon S3 upload: Start');
527
- $amazons3_result = $this->amazons3_backup($account_info['iwp_amazon_s3']);
528
- iwp_mmb_print_flush('Amazon S3 upload: End');
529
- if ($amazons3_result !== true && $del_host_file) {
530
- @unlink($backup_file);
531
- }
532
- if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
533
- return $amazons3_result;
534
- }
535
- $this->wpdb_reconnect();
536
- $this->update_status($task_name, 's3', true);
537
- }
538
-
539
- if (isset($account_info['iwp_dropbox']) && !empty($account_info['iwp_dropbox'])) {
540
- $this->update_status($task_name, 'dropbox');
541
- $account_info['iwp_dropbox']['backup_file'] = $backup_file;
542
- iwp_mmb_print_flush('Dropbox upload: Start');
543
- $dropbox_result = $this->dropbox_backup($account_info['iwp_dropbox']);
544
- iwp_mmb_print_flush('Dropbox upload: End');
545
- if ($dropbox_result !== true && $del_host_file) {
546
- @unlink($backup_file);
547
- }
548
-
549
- if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
550
- return $dropbox_result;
551
- }
552
- $this->wpdb_reconnect();
553
- $this->update_status($task_name, 'dropbox', true);
554
- }
555
-
556
- if ($del_host_file) {
557
- @unlink($backup_file);
558
- }
559
-
560
- } //end additional
561
-
562
- $this->update_status($task_name,'finished',true);
563
-
564
- return $backup_url; //Return url to backup file
565
- }
566
-
567
-
568
- function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
569
- {
570
-
571
- global $zip_errors;
572
- $sys = substr(PHP_OS, 0, 3);
573
-
574
- $this->update_status($task_name, 'db_dump');
575
- $GLOBALS['fail_safe_db'] = $this->tasks[$task_name]['task_args']['fail_safe_db'];
576
- $db_result = $this->backup_db();
577
-
578
- if ($db_result == false) {
579
- return array(
580
- 'error' => 'Failed to backup database.'
581
- );
582
- } else if (is_array($db_result) && isset($db_result['error'])) {
583
- return array(
584
- 'error' => $db_result['error']
585
- );
586
- }
587
-
588
- $this->update_status($task_name, 'db_dump', true);
589
- $this->update_status($task_name, 'db_zip');
590
-
591
- /*zip_backup_db*/
592
- $fail_safe_files = $this->tasks[$task_name]['task_args']['fail_safe_files'];
593
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
594
-
595
- if($fail_safe_files){
596
- $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
597
- }
598
- else{
599
- $comp_level = $disable_comp ? '-0' : '-1';
600
- $zip = $this->get_zip();
601
- iwp_mmb_print_flush('DB ZIP CMD: Start');
602
- //Add database file
603
- chdir(IWP_BACKUP_DIR);
604
- $command = "$zip -q -r $comp_level $backup_file 'iwp_db'";
605
- ob_start();
606
- $result = $this->iwp_mmb_exec($command);
607
- ob_get_clean();
608
- iwp_mmb_print_flush('DB ZIP CMD: End');
609
- /*zip_backup_db*/
610
-
611
- if(!$result){
612
- $zip_archive_db_result = false;
613
- if (class_exists("ZipArchive")) {
614
- iwp_mmb_print_flush('DB ZIP Archive: Start');
615
- $this->_log("DB zip, fallback to ZipArchive");
616
- $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
617
- iwp_mmb_print_flush('DB ZIP Archive: End');
618
- }
619
-
620
- if (!$zip_archive_db_result) {
621
- $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
622
- }
623
- }
624
- }
625
- @unlink($db_result);
626
- @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
627
- @rmdir(IWP_DB_DIR);
628
-
629
- $this->update_status($task_name, 'db_zip', true);
630
-
631
-
632
- //Always remove backup folders
633
- $remove = array(
634
- trim(basename(WP_CONTENT_DIR)) . "/infinitewp/backups",
635
- trim(basename(WP_CONTENT_DIR)) . "/" . md5('iwp_mmb-client') . "/iwp_backups",
636
- trim(basename(WP_CONTENT_DIR)) . "/cache",
637
- trim(basename(WP_CONTENT_DIR)) . "/w3tc"
638
- );
639
-
640
- $exclude = array_merge($exclude, $remove);
641
-
642
- //Exclude paths
643
- $exclude_data = "-x";
644
-
645
- $exclude_file_data = '';
646
-
647
- if (!empty($exclude) && is_array($exclude)) {
648
- foreach ($exclude as $data) {
649
- if(empty($data))
650
- continue;
651
- if (is_dir(ABSPATH . $data)) {
652
- if ($sys == 'WIN')
653
- $exclude_data .= " $data/*.*";
654
- else
655
- $exclude_data .= " '$data/*'";
656
- }else {
657
- if ($sys == 'WIN'){
658
- if(file_exists(ABSPATH . $data)){
659
- $exclude_data .= " $data";
660
- $exclude_file_data .= " $data";
661
- }
662
- }else {
663
- if(file_exists(ABSPATH . $data)){
664
- $exclude_data .= " '$data'";
665
- $exclude_file_data .= " '$data'";
666
- }
667
- }
668
- }
669
- }
670
- }
671
-
672
- if($exclude_file_data){
673
- $exclude_file_data = "-x".$exclude_file_data;
674
- }
675
-
676
- /* foreach ($remove as $data) {
677
- if(empty($data))
678
- continue;
679
- if ($sys == 'WIN')
680
- $exclude_data .= " $data/*.*";
681
- else
682
- $exclude_data .= " '$data/*'";
683
- }*/ //commented for pclzip modifications
684
-
685
- //Include paths by default
686
- $add = array(
687
- trim(WPINC),
688
- trim(basename(WP_CONTENT_DIR)),
689
- "wp-admin"
690
- );
691
-
692
- $include_data = ". -i";
693
- foreach ($add as $data) {
694
- if ($sys == 'WIN')
695
- $include_data .= " $data/*.*";
696
- else
697
- $include_data .= " '$data/*'";
698
- }
699
-
700
- //Additional includes?
701
- if (!empty($include) && is_array($include)) {
702
- foreach ($include as $data) {
703
- if(empty($data))
704
- continue;
705
- if ($data) {
706
- if ($sys == 'WIN')
707
- $include_data .= " $data/*.*";
708
- else
709
- $include_data .= " '$data/*'";
710
- }
711
- }
712
- }
713
-
714
- $this->update_status($task_name, 'files_zip');
715
- chdir(ABSPATH);
716
-
717
- if($fail_safe_files){
718
- $this->fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove);
719
- }
720
- else{
721
- $do_cmd_zip_alternative = false;
722
- @copy($backup_file, $backup_file.'_2');
723
-
724
- iwp_mmb_print_flush('Files ZIP CMD: Start');
725
- $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
726
- ob_start();
727
- $result_f = $this->iwp_mmb_exec($command, false, true);
728
- ob_get_clean();
729
- iwp_mmb_print_flush('Files ZIP CMD: 1/2 over');
730
- if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
731
- $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
732
- ob_start();
733
- $result_d = $this->iwp_mmb_exec($command, false, true);
734
- ob_get_clean();
735
- if ($result_d && $result_d != 18) {
736
- @unlink($backup_file);
737
- $do_cmd_zip_alternative = true;
738
-
739
-
740
- if($result_d > 0 && $result_d < 18){
741
- //return array(
742
- // 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
743
- // );
744
- iwp_mmb_print_flush('Files ZIP CMD: Failed to archive files (' . $zip_errors[$result_d] . ') .');
745
- }
746
- else{
747
- //return array(
748
- // 'error' => 'Failed to archive files.'
749
- //);
750
- iwp_mmb_print_flush('Files ZIP CMD: Failed to archive files.');
751
- }
752
- }
753
- }
754
-
755
- if(!$do_cmd_zip_alternative){//if FILE ZIP CMD successful
756
- @unlink($backup_file.'_2');
757
- }
758
-
759
- iwp_mmb_print_flush('Files ZIP CMD: End');
760
- if (($result_f && $result_f != 18) || ($do_cmd_zip_alternative)) {
761
-
762
- if($do_cmd_zip_alternative){
763
- @copy($backup_file.'_2', $backup_file);
764
- @unlink($backup_file.'_2');
765
- }
766
-
767
- $zip_archive_result = false;
768
- if (class_exists("ZipArchive")) {
769
- iwp_mmb_print_flush('Files ZIP Archive: Start');
770
- $this->_log("Files zip fallback to ZipArchive");
771
- $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
772
- iwp_mmb_print_flush('Files ZIP Archive: End');
773
- }
774
-
775
-
776
- if (!$zip_archive_result) {
777
- $this->fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove);
778
- }
779
- }
780
- }
781
-
782
- //Reconnect
783
- $this->wpdb_reconnect();
784
-
785
- $this->update_status($task_name, 'files_zip', true);
786
- return true;
787
- }
788
-
789
-
790
- function fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove){ //Try pclZip
791
- //$this->back_hack($task_name, 'Files ZIP PCL: Start');
792
- iwp_mmb_print_flush('Files ZIP PCL: Start');
793
- if (!isset($archive)) {
794
- define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
795
- //require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
796
- require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
797
- $archive = new IWPPclZip($backup_file);
798
- }
799
-
800
- //Include paths
801
- $include_data = array();
802
- if (!empty($include) && is_array($include)) {
803
- foreach ($include as $data) {
804
- if ($data && file_exists(ABSPATH . $data))
805
- $include_data[] = ABSPATH . $data . '/';
806
- }
807
- }
808
-
809
- foreach ($add as $data) {
810
- if (file_exists(ABSPATH . $data))
811
- $include_data[] = ABSPATH . $data . '/';
812
- }
813
-
814
- //Include root files
815
- if ($handle = opendir(ABSPATH)) {
816
- while (false !== ($file = readdir($handle))) {
817
- if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
818
- $include_data[] = ABSPATH . $file;
819
- }
820
- }
821
- closedir($handle);
822
- }
823
-
824
- //exclude paths
825
- $exclude_data = array();
826
- if (!empty($exclude) && is_array($exclude)) {
827
- foreach ($exclude as $data) {
828
- if (is_dir(ABSPATH . $data))
829
- $exclude_data[] = $data . '/';
830
- else
831
- $exclude_data[] = $data;
832
- }
833
- }
834
-
835
- foreach ($remove as $rem) {
836
- $exclude_data[] = $rem . '/';
837
- }
838
-
839
- if($fail_safe_files && $disable_comp){
840
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_NO_COMPRESSION, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
841
- }
842
- elseif(!$fail_safe_files && $disable_comp){
843
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_NO_COMPRESSION);
844
- }
845
- elseif($fail_safe_files && !$disable_comp){
846
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
847
- }
848
- else{
849
- $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data);
850
- }
851
-
852
- iwp_mmb_print_flush('Files ZIP PCL: End');
853
-
854
- if (!$result) {
855
- @unlink($backup_file);
856
- return array(
857
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
858
- );
859
- }
860
- //}
861
- }
862
- //Reconnect
863
- function fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp){
864
- //$this->back_hack($task_name, 'DB ZIP PCL: Start');
865
- iwp_mmb_print_flush('DB ZIP PCL: Start');
866
- define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
867
- require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
868
- $archive = new IWPPclZip($backup_file);
869
-
870
- if($fail_safe_files && $disable_comp){
871
- $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
872
- }
873
- elseif(!$fail_safe_files && $disable_comp){
874
- $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
875
- }
876
- elseif($fail_safe_files && !$disable_comp){
877
- $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
878
- }
879
- else{
880
- $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR);
881
- }
882
- //$this->back_hack($task_name, 'DB ZIP PCL: End');
883
- iwp_mmb_print_flush('DB ZIP PCL: End');
884
-
885
- @unlink($db_result);
886
- @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
887
- @rmdir(IWP_DB_DIR);
888
-
889
- if (!$result_db) {
890
- return array(
891
- 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
892
- );
893
- }
894
- }
895
- /**
896
- * Zipping database dump and index.php in folder iwp_db by ZipArchive class, requires php zip extension.
897
- *
898
- * @param string $task_name the name of backup task
899
- * @param string $db_result relative path to database dump file
900
- * @param string $backup_file absolute path to zip file
901
- * @return bool is compress successful or not
902
- */
903
- function zip_archive_backup_db($task_name, $db_result, $backup_file) {
904
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
905
- if (!$disable_comp) {
906
- $this->_log("Compression is not supported by ZipArchive");
907
- }
908
- $zip = new ZipArchive();
909
- $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
910
- if ($result === true) {
911
- $result = $result && $zip->addFile(IWP_BACKUP_DIR.'/iwp_db/index.php', "iwp_db/index.php"); // Tries to add iwp_db/index.php to $backup_file
912
- $result = $result && $zip->addFile($db_result, "iwp_db/" . basename($db_result)); // Tries to add db dump form iwp_db dir to $backup_file
913
- $result = $result && $zip->close(); // Tries to close $backup_file
914
- } else {
915
- $result = false;
916
- }
917
-
918
- return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
919
- }
920
-
921
- /**
922
- * Zipping whole site root folder and append to backup file with database dump
923
- * by ZipArchive class, requires php zip extension.
924
- *
925
- * @param string $task_name the name of backup task
926
- * @param string $backup_file absolute path to zip file
927
- * @param array $exclude array of files of folders to exclude, relative to site's root
928
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
929
- * @return array|bool true if successful or an array with error message if not
930
- */
931
- function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
932
-
933
- $filelist = $this->get_backup_files($exclude, $include);
934
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
935
- if (!$disable_comp) {
936
- $this->_log("Compression is not supported by ZipArchive");
937
- }
938
- $zip = new ZipArchive();
939
- if ($overwrite) {
940
- $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
941
- } else {
942
- $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
943
- }
944
- if ($result === true) {
945
- foreach ($filelist as $file) {
946
- iwp_mmb_auto_print('zip_archive_backup');
947
- $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
948
- }
949
- $result = $result && $zip->close(); // Tries to close $backup_file
950
- } else {
951
- $result = false;
952
- }
953
- return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
954
- }
955
-
956
-
957
- /**
958
- * Gets an array of relative paths of all files in site root recursively.
959
- * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
960
- * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
961
- *
962
- * @param array $exclude array of files of folders to exclude, relative to site's root
963
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
964
- * @return array array with all files in site root dir
965
- */
966
- function get_backup_files($exclude, $include) {
967
-
968
- $add = array(
969
- trim(WPINC),
970
- trim(basename(WP_CONTENT_DIR)),
971
- "wp-admin"
972
- );
973
-
974
- $include = array_merge($add, $include);
975
-
976
- $filelist = array();
977
- if ($handle = opendir(ABSPATH)) {
978
- while (false !== ($file = readdir($handle))) {
979
- if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
980
- $exclude[] = $file;
981
- }
982
- }
983
- closedir($handle);
984
- }
985
-
986
- $filelist = get_all_files_from_dir(ABSPATH, $exclude);
987
-
988
- return $filelist;
989
- }
990
-
991
-
992
- function backup_db()
993
- {
994
- $db_folder = IWP_DB_DIR . '/';
995
- if (!file_exists($db_folder)) {
996
- if (!mkdir($db_folder, 0755, true))
997
- return array(
998
- 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
999
- );
1000
- $db_index_file = '<?php
1001
- global $old_url, $old_file_path;
1002
- $old_url = \''.get_option('siteurl').'\';
1003
- $old_file_path = \''.ABSPATH.'\';
1004
- ';
1005
- @file_put_contents(IWP_BACKUP_DIR.'/iwp_db/index.php', $db_index_file);
1006
- }
1007
-
1008
- $file = $db_folder . DB_NAME . '.sql';
1009
-
1010
- if($GLOBALS['fail_safe_db']){
1011
- $result = $this->backup_db_php($file);
1012
- return $result;
1013
- }
1014
-
1015
- $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
1016
- return $result;
1017
- }
1018
-
1019
- function backup_db_dump($file)
1020
- {
1021
- global $wpdb;
1022
- $paths = $this->check_mysql_paths();
1023
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1024
- $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;
1025
- iwp_mmb_print_flush('DB DUMP CMD: Start');
1026
- ob_start();
1027
- $result = $this->iwp_mmb_exec($command);
1028
- ob_get_clean();
1029
- iwp_mmb_print_flush('DB DUMP CMD: End');
1030
-
1031
- if (!$result) { // Fallback to php
1032
- $result = $this->backup_db_php($file);
1033
- return $result;
1034
- }
1035
-
1036
- if (filesize($file) == 0 || !is_file($file) || !$result) {
1037
- @unlink($file);
1038
- return false;
1039
- } else {
1040
- return $file;
1041
- }
1042
- }
1043
-
1044
- function backup_db_php($file)
1045
- {
1046
- global $wpdb;
1047
-
1048
- if(empty($GLOBALS['fail_safe_db'])){
1049
- iwp_mmb_print_flush('DB DUMP PHP Normal: Start');
1050
- $fp = fopen( $file, 'w' );
1051
- if ( !mysql_ping( $wpdb->dbh ) ) {
1052
- mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
1053
- mysql_select_db( DB_NAME );
1054
- }
1055
- $_count = 0;
1056
- $insert_sql = '';
1057
- $result = mysql_query( 'SHOW TABLES' );
1058
- if(!$result)
1059
- {
1060
- return array(
1061
- 'error' => 'MySQL '.mysql_error()." "
1062
- );
1063
- }
1064
- while( $row = mysql_fetch_row( $result ) ) {
1065
- $tables[]=$row[0];
1066
- //array_push( $tables, $row[0] );
1067
- }
1068
-
1069
-
1070
- //$tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1071
- foreach ($tables as $table) {
1072
- iwp_mmb_auto_print('backup_db_php_normal');
1073
-
1074
- $insert_sql .= "DROP TABLE IF EXISTS $table;";
1075
- //create table
1076
- $table_descr_query = mysql_query("SHOW CREATE TABLE `$table`");
1077
- $fetch_table_descr_row = mysql_fetch_array( $table_descr_query );
1078
- $insert_sql .= "\n\n" . $fetch_table_descr_row[1] . ";\n\n";
1079
-
1080
- fwrite( $fp, $insert_sql );
1081
- $insert_sql = '';
1082
-
1083
- $table_query = mysql_query("SELECT * FROM `$table`");
1084
- $num_fields = mysql_num_fields($table_query);
1085
- while ( $fetch_row = mysql_fetch_array( $table_query ) ) {
1086
- $insert_sql .= "INSERT INTO $table VALUES(";
1087
- for ( $n=1; $n<=$num_fields; $n++ ) {
1088
- $m = $n - 1;
1089
-
1090
- if ( $fetch_row[$m] === NULL ) {
1091
- $insert_sql .= "NULL, ";
1092
- } else {
1093
- $insert_sql .= "'" . mysql_real_escape_string( $fetch_row[$m] ) . "', ";
1094
- }
1095
- }
1096
- $insert_sql = substr( $insert_sql, 0, -2 );
1097
- $insert_sql .= ");\n";
1098
-
1099
- fwrite( $fp, $insert_sql );
1100
- $insert_sql = '';
1101
-
1102
- // Help keep HTTP alive.
1103
- $_count++;
1104
- if ($_count >= 400) {
1105
- echo ' ';
1106
- flush();
1107
- $_count = 0;
1108
- }
1109
- } // End foreach $tables.
1110
-
1111
- $insert_sql .= "\n\n\n";
1112
-
1113
- // testing: mysql_close( $wpdb->dbh );
1114
- // Verify database is still connected and working properly. Sometimes mysql runs out of memory and dies in the above foreach.
1115
- // No point in reconnecting as we can NOT trust that our dump was succesful anymore (it most likely was not).
1116
- if ( @mysql_ping( $wpdb->dbh ) ) { // Still connected to database.
1117
- mysql_free_result( $table_query ); // Free memory.
1118
- } /*else { // Database not connected.
1119
-
1120
- return false;
1121
- }*/
1122
-
1123
- // Help keep HTTP alive.
1124
- echo ' ';
1125
- flush();
1126
-
1127
- //unset( $tables[$table_key] );
1128
- }
1129
- fclose( $fp );
1130
- unset ($fp);
1131
- iwp_mmb_print_flush('DB DUMP PHP Normal: End');
1132
- }
1133
- else{
1134
- iwp_mmb_print_flush('DB DUMP PHP Fail-safe: Start');
1135
- file_put_contents($file, '');//safe to reset any old data
1136
- $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1137
- foreach ($tables as $table) {
1138
-
1139
- //drop existing table
1140
- $dump_data = "DROP TABLE IF EXISTS $table[0];";
1141
- file_put_contents($file, $dump_data, FILE_APPEND);
1142
- //create table
1143
- $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
1144
- $dump_data = "\n\n" . $create_table[1] . ";\n\n";
1145
- file_put_contents($file, $dump_data, FILE_APPEND);
1146
-
1147
- $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
1148
- if ($count > 100)
1149
- $count = ceil($count / 100);
1150
- else if ($count > 0)
1151
- $count = 1;
1152
-
1153
- for ($i = 0; $i < $count; $i++) {
1154
- iwp_mmb_auto_print('backup_db_php_fail_safe');
1155
- $low_limit = $i * 100;
1156
- $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
1157
- $rows = $wpdb->get_results($qry, ARRAY_A);
1158
- if (is_array($rows)) {
1159
- foreach ($rows as $row) {
1160
- //insert single row
1161
- $dump_data = "INSERT INTO $table[0] VALUES(";
1162
- $num_values = count($row);
1163
- $j = 1;
1164
- foreach ($row as $value) {
1165
- $value = addslashes($value);
1166
- $value = preg_replace("/\n/Ui", "\\n", $value);
1167
- $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
1168
- $j++;
1169
- unset($value);
1170
- }
1171
- $dump_data .= ");\n";
1172
- file_put_contents($file, $dump_data, FILE_APPEND);
1173
- }
1174
- }
1175
- }
1176
- $dump_data = "\n\n\n";
1177
- file_put_contents($file, $dump_data, FILE_APPEND);
1178
-
1179
- unset($rows);
1180
- unset($dump_data);
1181
- }
1182
- iwp_mmb_print_flush('DB DUMP PHP Fail-safe: End');
1183
- }
1184
-
1185
- if (filesize($file) == 0 || !is_file($file)) {
1186
- @unlink($file);
1187
- return array(
1188
- 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
1189
- );
1190
- }
1191
-
1192
- return $file;
1193
-
1194
- }
1195
-
1196
- /**
1197
- * Copies a directory from one location to another via the WordPress Filesystem Abstraction.
1198
- * Assumes that WP_Filesystem() has already been called and setup.
1199
- *
1200
- * @since 2.5.0
1201
- *
1202
- * @param string $from source directory
1203
- * @param string $to destination directory
1204
- * @param array $skip_list a list of files/folders to skip copying
1205
- * @return mixed WP_Error on failure, True on success.
1206
- */
1207
- function iwp_mmb_direct_to_any_copy_dir($from, $to, $skip_list = array() ) {//$from => direct file system, $to => automatic filesystem
1208
- global $wp_filesystem;
1209
-
1210
- $wp_temp_direct = new WP_Filesystem_Direct('');
1211
-
1212
-
1213
- $dirlist = $wp_temp_direct->dirlist($from);
1214
-
1215
- $from = trailingslashit($from);
1216
- $to = trailingslashit($to);
1217
-
1218
- $skip_regex = '';
1219
- foreach ( (array)$skip_list as $key => $skip_file )
1220
- $skip_regex .= preg_quote($skip_file, '!') . '|';
1221
-
1222
- if ( !empty($skip_regex) )
1223
- $skip_regex = '!(' . rtrim($skip_regex, '|') . ')$!i';
1224
-
1225
- foreach ( (array) $dirlist as $filename => $fileinfo ) {
1226
- if ( !empty($skip_regex) )
1227
- if ( preg_match($skip_regex, $from . $filename) )
1228
- continue;
1229
-
1230
- if ( 'f' == $fileinfo['type'] ) {
1231
- if ( ! $this->iwp_mmb_direct_to_any_copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) {
1232
- // If copy failed, chmod file to 0644 and try again.
1233
- $wp_filesystem->chmod($to . $filename, 0644);
1234
- if ( ! $this->iwp_mmb_direct_to_any_copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) )
1235
- return new WP_Error('copy_failed', __('Could not copy file.'), $to . $filename);
1236
- }
1237
- } elseif ( 'd' == $fileinfo['type'] ) {
1238
- if ( !$wp_filesystem->is_dir($to . $filename) ) {
1239
- if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) )
1240
- return new WP_Error('mkdir_failed', __('Could not create directory.'), $to . $filename);
1241
- }
1242
- $result = $this->iwp_mmb_direct_to_any_copy_dir($from . $filename, $to . $filename, $skip_list);
1243
- if ( is_wp_error($result) )
1244
- return $result;
1245
- }
1246
- }
1247
- return true;
1248
- }
1249
-
1250
- function iwp_mmb_direct_to_any_copy($source, $destination, $overwrite = false, $mode = false){
1251
- global $wp_filesystem;
1252
- if($wp_filesystem->method == 'direct'){
1253
- return $wp_filesystem->copy($source, $destination, $overwrite, $mode);
1254
- }
1255
- elseif($wp_filesystem->method == 'ftpext' || $wp_filesystem->method == 'ftpsockets'){
1256
- if ( ! $overwrite && $wp_filesystem->exists($destination) )
1257
- return false;
1258
- //$content = $this->get_contents($source);
1259
- // if ( false === $content)
1260
- // return false;
1261
-
1262
- //put content
1263
- //$tempfile = wp_tempnam($file);
1264
- $source_handle = fopen($source, 'r');
1265
- if ( ! $source_handle )
1266
- return false;
1267
-
1268
- //fwrite($temp, $contents);
1269
- //fseek($temp, 0); //Skip back to the start of the file being written to
1270
-
1271
- $sample_content = fread($source_handle, (1024 * 1024 * 2));//1024 * 1024 * 2 => 2MB
1272
- fseek($source_handle, 0); //Skip back to the start of the file being written to
1273
-
1274
- $type = $wp_filesystem->is_binary($sample_content) ? FTP_BINARY : FTP_ASCII;
1275
- unset($sample_content);
1276
- if($wp_filesystem->method == 'ftpext'){
1277
- $ret = @ftp_fput($wp_filesystem->link, $destination, $source_handle, $type);
1278
- }
1279
- elseif($wp_filesystem->method == 'ftpsockets'){
1280
- $wp_filesystem->ftp->SetType($type);
1281
- $ret = $wp_filesystem->ftp->fput($destination, $source_handle);
1282
- }
1283
-
1284
- fclose($source_handle);
1285
- unlink($source);//to immediately save system space
1286
- //unlink($tempfile);
1287
-
1288
- $wp_filesystem->chmod($destination, $mode);
1289
-
1290
- return $ret;
1291
-
1292
- //return $this->put_contents($destination, $content, $mode);
1293
- }
1294
- }
1295
-
1296
-
1297
- function restore($args)
1298
- {
1299
-
1300
- global $wpdb, $wp_filesystem;
1301
- if (empty($args)) {
1302
- return false;
1303
- }
1304
-
1305
- extract($args);
1306
- $this->set_memory();
1307
-
1308
- $unlink_file = true; //Delete file after restore
1309
-
1310
- include_once ABSPATH . 'wp-admin/includes/file.php';
1311
-
1312
- //Detect source
1313
- if ($backup_url) {
1314
- //This is for clone (overwrite)
1315
-
1316
- $backup_file = download_url($backup_url);
1317
- if (is_wp_error($backup_file)) {
1318
- return array(
1319
- 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
1320
- );
1321
- }
1322
- $what = 'full';
1323
- } else {
1324
- $tasks = $this->tasks;
1325
- $task = $tasks[$task_name];
1326
- if (isset($task['task_results'][$result_id]['server'])) {
1327
- $backup_file = $task['task_results'][$result_id]['server']['file_path'];
1328
- $unlink_file = false; //Don't delete file if stored on server
1329
-
1330
- } elseif (isset($task['task_results'][$result_id]['ftp'])) {
1331
- $ftp_file = $task['task_results'][$result_id]['ftp'];
1332
- $args = $task['task_args']['account_info']['iwp_ftp'];
1333
- $args['backup_file'] = $ftp_file;
1334
- iwp_mmb_print_flush('FTP download: Start');
1335
- $backup_file = $this->get_ftp_backup($args);
1336
- iwp_mmb_print_flush('FTP download: End');
1337
- if ($backup_file == false) {
1338
- return array(
1339
- 'error' => 'Failed to download file from FTP.'
1340
- );
1341
- }
1342
- } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
1343
- $amazons3_file = $task['task_results'][$result_id]['amazons3'];
1344
- $args = $task['task_args']['account_info']['iwp_amazon_s3'];
1345
- $args['backup_file'] = $amazons3_file;
1346
- iwp_mmb_print_flush('Amazon S3 download: Start');
1347
- $backup_file = $this->get_amazons3_backup($args);
1348
- iwp_mmb_print_flush('Amazon S3 download: End');
1349
- if ($backup_file == false) {
1350
- return array(
1351
- 'error' => 'Failed to download file from Amazon S3.'
1352
- );
1353
- }
1354
- } elseif(isset($task['task_results'][$result_id]['dropbox'])){
1355
- $dropbox_file = $task['task_results'][$result_id]['dropbox'];
1356
- $args = $task['task_args']['account_info']['iwp_dropbox'];
1357
- $args['backup_file'] = $dropbox_file;
1358
- iwp_mmb_print_flush('Dropbox download: Start');
1359
- $backup_file = $this->get_dropbox_backup($args);
1360
- iwp_mmb_print_flush('Dropbox download: End');
1361
-
1362
- if ($backup_file == false) {
1363
- return array(
1364
- 'error' => 'Failed to download file from Dropbox.'
1365
- );
1366
- }
1367
- }
1368
-
1369
-
1370
- $what = $tasks[$task_name]['task_args']['what'];
1371
- }
1372
-
1373
-
1374
-
1375
- $this->wpdb_reconnect();
1376
-
1377
- /////////////////// dev ////////////////////////
1378
-
1379
-
1380
- if (!$this->is_server_writable()) {
1381
- return array(
1382
- 'error' => 'Failed, please add FTP details'
1383
- );
1384
- }
1385
-
1386
- $url = wp_nonce_url('index.php?page=iwp_no_page','iwp_fs_cred');
1387
- ob_start();
1388
- if (false === ($creds = request_filesystem_credentials($url, '', false, ABSPATH, null) ) ) {
1389
- return array(
1390
- 'error' => 'Unable to get file system credentials'
1391
- ); // stop processing here
1392
- }
1393
- ob_end_clean();
1394
-
1395
- if ( ! WP_Filesystem($creds, ABSPATH) ) {
1396
- //request_filesystem_credentials($url, '', true, false, null);
1397
- return array(
1398
- 'error' => 'Unable to initiate file system. Please check you have entered valid FTP credentials.'
1399
- ); // stop processing here
1400
- //return;
1401
- }
1402
-
1403
- require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php');//will be used to copy from temp directory
1404
-
1405
- // do process
1406
- $temp_dir = get_temp_dir();
1407
- $new_temp_folder = untrailingslashit($temp_dir);
1408
- $temp_uniq = md5(microtime(1));//should be random
1409
- while (is_dir($new_temp_folder .'/'. $temp_uniq )) {
1410
- $temp_uniq = md5(microtime(1));
1411
- }
1412
- $new_temp_folder = trailingslashit($new_temp_folder .'/'. $temp_uniq);
1413
- $is_dir_created = mkdir($new_temp_folder);// new folder should be empty
1414
- if(!$is_dir_created){
1415
- return array(
1416
- 'error' => 'Unable to create a temporary directory.'
1417
- );
1418
- }
1419
-
1420
- //echo '<pre>$new_temp_folder:'; var_dump($new_temp_folder); echo '</pre>';
1421
-
1422
-
1423
- $remote_abspath = $wp_filesystem->abspath();
1424
- if(!empty($remote_abspath)){
1425
- $remote_abspath = trailingslashit($remote_abspath);
1426
- }else{
1427
- return array(
1428
- 'error' => 'Unable to locate WP root directory using file system.'
1429
- );
1430
- }
1431
-
1432
- //global $wp_filesystem;
1433
- // $wp_filesystem->put_contents(
1434
- // '/tmp/example.txt',
1435
- // 'Example contents of a file',
1436
- // FS_CHMOD_FILE // predefined mode settings for WP files
1437
- // );
1438
-
1439
- /////////////////// dev ////////////////////////
1440
-
1441
- if ($backup_file && file_exists($backup_file)) {
1442
- if ($overwrite) {//clone only fresh or existing to existing
1443
- //Keep old db credentials before overwrite
1444
- if (!$wp_filesystem->copy($remote_abspath . 'wp-config.php', $remote_abspath . 'iwp-temp-wp-config.php', true)) {
1445
- if($unlink_file) @unlink($backup_file);
1446
- return array(
1447
- 'error' => 'Error creating wp-config. Please check your write permissions.'
1448
- );
1449
- }
1450
-
1451
- $db_host = DB_HOST;
1452
- $db_user = DB_USER;
1453
- $db_password = DB_PASSWORD;
1454
- $home = rtrim(get_option('home'), "/");
1455
- $site_url = get_option('site_url');
1456
-
1457
- $clone_options = array();
1458
- if (trim($clone_from_url) || trim($iwp_clone) || trim($maintain_old_key)) {
1459
-
1460
- $clone_options['iwp_client_nossl_key'] = get_option('iwp_client_nossl_key');
1461
- $clone_options['iwp_client_public_key'] = get_option('iwp_client_public_key');
1462
- $clone_options['iwp_client_action_message_id'] = get_option('iwp_client_action_message_id');
1463
-
1464
- }
1465
-
1466
- $clone_options['iwp_client_backup_tasks'] = serialize(get_option('iwp_client_backup_tasks'));
1467
- $clone_options['iwp_client_notifications'] = serialize(get_option('iwp_client_notifications'));
1468
- $clone_options['iwp_client_pageview_alerts'] = serialize(get_option('iwp_client_pageview_alerts'));
1469
-
1470
-
1471
- } else {
1472
- $restore_options = array();
1473
- $restore_options['iwp_client_notifications'] = serialize(get_option('iwp_client_notifications'));
1474
- $restore_options['iwp_client_pageview_alerts'] = serialize(get_option('iwp_client_pageview_alerts'));
1475
- $restore_options['iwp_client_user_hit_count'] = serialize(get_option('iwp_client_user_hit_count'));
1476
- $restore_options['iwp_client_backup_tasks'] = serialize(get_option('iwp_client_backup_tasks'));
1477
- }
1478
-
1479
-
1480
-
1481
-
1482
- //Backup file will be extracted to a temporary path
1483
-
1484
- //chdir(ABSPATH);
1485
- $unzip = $this->get_unzip();
1486
- $command = "$unzip -o $backup_file -d $new_temp_folder";
1487
- iwp_mmb_print_flush('ZIP Extract CMD: Start');
1488
- ob_start();
1489
- $result = $this->iwp_mmb_exec($command);
1490
- ob_get_clean();
1491
- iwp_mmb_print_flush('ZIP Extract CMD: End');
1492
-
1493
- if (!$result) { //fallback to pclzip
1494
- define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
1495
- //require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
1496
- require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
1497
- iwp_mmb_print_flush('ZIP Extract PCL: Start');
1498
- $archive = new IWPPclZip($backup_file);
1499
- $result = $archive->extract(PCLZIP_OPT_PATH, $new_temp_folder, PCLZIP_OPT_REPLACE_NEWER);
1500
- iwp_mmb_print_flush('ZIP Extract PCL: End');
1501
- }
1502
- $this->wpdb_reconnect();
1503
-
1504
- if ($unlink_file) {
1505
- @unlink($backup_file);
1506
- }
1507
-
1508
- if (!$result) {
1509
- return array(
1510
- 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
1511
- );
1512
- }
1513
-
1514
- $db_result = $this->restore_db($new_temp_folder);
1515
-
1516
- if (!$db_result) {
1517
- return array(
1518
- 'error' => 'Error restoring database.'
1519
- );
1520
- } else if(is_array($db_result) && isset($db_result['error'])){
1521
- return array(
1522
- 'error' => $db_result['error']
1523
- );
1524
- }
1525
-
1526
- } else {
1527
- return array(
1528
- 'error' => 'Backup file not found.'
1529
- );
1530
- }
1531
-
1532
-
1533
- //copy files from temp to ABSPATH
1534
- $copy_result = $this->iwp_mmb_direct_to_any_copy_dir($new_temp_folder, $remote_abspath);
1535
-
1536
- if ( is_wp_error($copy_result) ){
1537
- $wp_temp_direct2 = new WP_Filesystem_Direct('');
1538
- $wp_temp_direct2->delete($new_temp_folder, true);
1539
- return $copy_result;
1540
- }
1541
-
1542
-
1543
- $this->wpdb_reconnect();
1544
-
1545
-
1546
-
1547
- //Replace options and content urls
1548
- if ($overwrite) {//fresh WP package or existing to existing site
1549
- //Get New Table prefix
1550
- $new_table_prefix = trim($this->get_table_prefix());
1551
- //Retrieve old wp_config
1552
- //@unlink(ABSPATH . 'wp-config.php');
1553
- $wp_filesystem->delete($remote_abspath . 'wp-config.php', false, 'f');
1554
- //Replace table prefix
1555
- //$lines = file(ABSPATH . 'iwp-temp-wp-config.php');
1556
- $lines = $wp_filesystem->get_contents_array($remote_abspath . 'iwp-temp-wp-config.php');
1557
-
1558
- $new_lines = '';
1559
- foreach ($lines as $line) {
1560
- if (strstr($line, '$table_prefix')) {
1561
- $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
1562
- }
1563
- $new_lines .= $line;
1564
- //file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
1565
- }
1566
-
1567
- $wp_filesystem->put_contents($remote_abspath . 'wp-config.php', $new_lines);
1568
-
1569
- //@unlink(ABSPATH . 'iwp-temp-wp-config.php');
1570
- $wp_filesystem->delete($remote_abspath . 'iwp-temp-wp-config.php', false, 'f');
1571
-
1572
- //Replace options
1573
- $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
1574
- $old = $wpdb->get_var($query);
1575
- $old = rtrim($old, "/");
1576
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'home'";
1577
- $wpdb->query($wpdb->prepare($query, $home));
1578
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'siteurl'";
1579
- $wpdb->query($wpdb->prepare($query, $home));
1580
- //Replace content urls
1581
-
1582
- $regexp1 = 'src="(.*)'.$old.'(.*)"';
1583
- $regexp2 = 'href="(.*)'.$old.'(.*)"';
1584
- $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, %s,%s) WHERE post_content REGEXP %s OR post_content REGEXP %s";
1585
- $wpdb->query($wpdb->prepare($query, $old, $home, $regexp1, $regexp2));
1586
-
1587
- if (trim($new_password)) {
1588
- $new_password = wp_hash_password($new_password);
1589
- }
1590
- if (!trim($clone_from_url) && !trim($iwp_clone)) {
1591
- if ($new_user && $new_password) {
1592
- $query = "UPDATE " . $new_table_prefix . "users SET user_login = %s, user_pass = %s WHERE user_login = %s";
1593
- $wpdb->query($wpdb->prepare($query, $new_user, $new_password, $old_user));
1594
- }
1595
- } else {
1596
-
1597
- // if ($iwp_clone) {
1598
- if ($admin_email) {
1599
- //Clean Install
1600
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'admin_email'";
1601
- $wpdb->query($wpdb->prepare($query, $admin_email));
1602
- $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
1603
- $temp_user = $wpdb->get_row($query);
1604
- if (!empty($temp_user)) {
1605
- $query = "UPDATE " . $new_table_prefix . "users SET user_email=%s, user_login = %s, user_pass = %s WHERE user_login = %s";
1606
- $wpdb->query($wpdb->prepare($query, $admin_email, $new_user, $new_password, $temp_user->user_login));
1607
- }
1608
-
1609
- }
1610
- // }
1611
-
1612
- //if ($clone_from_url) {
1613
- if ($new_user && $new_password) {
1614
- $query = "UPDATE " . $new_table_prefix . "users SET user_pass = %s WHERE user_login = %s";
1615
- $wpdb->query($wpdb->prepare($query, $new_password, $new_user));
1616
- }
1617
- // }
1618
-
1619
- }
1620
-
1621
- if (is_array($clone_options) && !empty($clone_options)) {
1622
- foreach ($clone_options as $key => $option) {
1623
- if (!empty($key)) {
1624
- $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = %s";
1625
- $res = $wpdb->get_var($wpdb->prepare($query, $key));
1626
- if ($res == false) {
1627
- $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES(%s,%s)";
1628
- $wpdb->query($wpdb->prepare($query, $option, $key));
1629
- } else {
1630
- $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = %s";
1631
- $wpdb->query($wpdb->prepare($query, $option, $key));
1632
- }
1633
- }
1634
- }
1635
- }
1636
-
1637
- //Remove hit count
1638
- $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'iwp_client_user_hit_count'";
1639
- $wpdb->query($query);
1640
-
1641
- //Check for .htaccess permalinks update
1642
- $this->replace_htaccess($home, $remote_abspath);
1643
- } else {
1644
- //restore client options
1645
- if (is_array($restore_options) && !empty($restore_options)) {
1646
- foreach ($restore_options as $key => $option) {
1647
- if (!empty($key)) {
1648
- $query = "SELECT option_value FROM " . $wpdb->base_prefix . "options WHERE option_name = %s";
1649
- $res = $wpdb->get_var($wpdb->prepare($query, $key));
1650
- if ($res == false) {
1651
- $query = "INSERT INTO " . $wpdb->base_prefix . "options (option_value,option_name) VALUES(%s,%s)";
1652
- $wpdb->query($wpdb->prepare($query, $option, $key));
1653
- } else {
1654
- $query = "UPDATE " . $wpdb->base_prefix . "options SET option_value = %s WHERE option_name = %s";
1655
- $wpdb->query($wpdb->prepare($query, $option, $key));
1656
- }
1657
- }
1658
-
1659
- /*$test = update_option($key,$option);*/
1660
- }
1661
- }
1662
- }
1663
-
1664
- //clear the temp directory
1665
- $wp_temp_direct2 = new WP_Filesystem_Direct('');
1666
- $wp_temp_direct2->delete($new_temp_folder, true);
1667
-
1668
- return !empty($new_user) ? $new_user : true ;
1669
- }
1670
-
1671
- function restore_db($new_temp_folder)
1672
- {
1673
- global $wpdb;
1674
- $paths = $this->check_mysql_paths();
1675
- $file_path = $new_temp_folder . '/iwp_db';
1676
- @chmod($file_path,0755);
1677
- $file_name = glob($file_path . '/*.sql');
1678
- $file_name = $file_name[0];
1679
-
1680
- if(!$file_name){
1681
- return array('error' => 'Cannot access database file.');
1682
- }
1683
-
1684
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1685
- $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
1686
- iwp_mmb_print_flush('DB Restore CMD: Start');
1687
- ob_start();
1688
- $result = $this->iwp_mmb_exec($command);
1689
- ob_get_clean();
1690
- iwp_mmb_print_flush('DB Restore CMD: End');
1691
- if (!$result) {
1692
- //try php
1693
- $this->restore_db_php($file_name);
1694
- }
1695
-
1696
-
1697
- @unlink($file_name);
1698
- @unlink(dirname($file_name).'/index.php');
1699
- @rmdir(dirname($file_name));//remove its folder
1700
- return true;
1701
- }
1702
-
1703
- function restore_db_php($file_name)
1704
- {
1705
-
1706
- $this->wpdb_reconnect();
1707
- global $wpdb;
1708
-
1709
- $wpdb->query("SET NAMES 'utf8'");
1710
-
1711
- $current_query = '';
1712
- // Read in entire file
1713
- $lines = file($file_name);
1714
- // Loop through each line
1715
- if(!empty($lines)){
1716
- foreach ($lines as $line) {
1717
- iwp_mmb_auto_print('restore_db_php');
1718
- // Skip it if it's a comment
1719
- if (substr($line, 0, 2) == '--' || $line == '')
1720
- continue;
1721
-
1722
- // Add this line to the current query
1723
- $current_query .= $line;
1724
- // If it has a semicolon at the end, it's the end of the query
1725
- if (substr(trim($line), -1, 1) == ';') {
1726
- // Perform the query
1727
- $result = $wpdb->query($current_query);
1728
- if ($result === false)
1729
- return false;
1730
- // Reset temp variable to empty
1731
- $current_query = '';
1732
- }
1733
- }
1734
- }
1735
-
1736
- return true;
1737
- }
1738
-
1739
- function get_table_prefix()
1740
- {
1741
- $lines = file(ABSPATH . 'wp-config.php');
1742
- foreach ($lines as $line) {
1743
- if (strstr($line, '$table_prefix')) {
1744
- $pattern = "/(\'|\")[^(\'|\")]*/";
1745
- preg_match($pattern, $line, $matches);
1746
- $prefix = substr($matches[0], 1);
1747
- return $prefix;
1748
- break;
1749
- }
1750
- }
1751
- return 'wp_'; //default
1752
- }
1753
-
1754
- function optimize_tables()
1755
- {
1756
- global $wpdb;
1757
- $query = 'SHOW TABLE STATUS';
1758
- $tables = $wpdb->get_results($query, ARRAY_A);
1759
- foreach ($tables as $table) {
1760
- if (in_array($table['Engine'], array(
1761
- 'MyISAM',
1762
- 'ISAM',
1763
- 'HEAP',
1764
- 'MEMORY',
1765
- 'ARCHIVE'
1766
- )))
1767
- $table_string .= $table['Name'] . ",";
1768
- elseif ($table['Engine'] == 'InnoDB') {
1769
- $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1770
- }
1771
- }
1772
-
1773
- if(!empty($table_string)){
1774
- $table_string = rtrim($table_string, ',');
1775
- $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1776
- }
1777
-
1778
- return $optimize ? true : false;
1779
- }
1780
-
1781
- ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1782
- function check_mysql_paths()
1783
- {
1784
- global $wpdb;
1785
- $paths = array(
1786
- 'mysql' => '',
1787
- 'mysqldump' => ''
1788
- );
1789
- if (substr(PHP_OS, 0, 3) == 'WIN') {
1790
- $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1791
- if ($mysql_install) {
1792
- $install_path = str_replace('\\', '/', $mysql_install->Value);
1793
- $paths['mysql'] = $install_path . 'bin/mysql.exe';
1794
- $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1795
- } else {
1796
- $paths['mysql'] = 'mysql.exe';
1797
- $paths['mysqldump'] = 'mysqldump.exe';
1798
- }
1799
- } else {
1800
- $paths['mysql'] = $this->iwp_mmb_exec('which mysql', true);
1801
- if (empty($paths['mysql']))
1802
- $paths['mysql'] = 'mysql'; // try anyway
1803
-
1804
- $paths['mysqldump'] = $this->iwp_mmb_exec('which mysqldump', true);
1805
- if (empty($paths['mysqldump']))
1806
- $paths['mysqldump'] = 'mysqldump'; // try anyway
1807
-
1808
- }
1809
-
1810
-
1811
- return $paths;
1812
- }
1813
-
1814
- //Check if exec, system, passthru functions exist
1815
- function check_sys()
1816
- {
1817
- if ($this->iwp_mmb_function_exists('exec'))
1818
- return 'exec';
1819
-
1820
- if ($this->iwp_mmb_function_exists('system'))
1821
- return 'system';
1822
-
1823
- if ($this->iwp_mmb_function_exists('passhtru'))
1824
- return 'passthru';
1825
-
1826
- return false;
1827
-
1828
- }
1829
-
1830
- function iwp_mmb_exec($command, $string = false, $rawreturn = false)
1831
- {
1832
- if ($command == '')
1833
- return false;
1834
-
1835
- if ($this->iwp_mmb_function_exists('exec')) {
1836
- $log = @exec($command, $output, $return);
1837
-
1838
- if ($string)
1839
- return $log;
1840
- if ($rawreturn)
1841
- return $return;
1842
-
1843
- return $return ? false : true;
1844
- } elseif ($this->iwp_mmb_function_exists('system')) {
1845
- $log = @system($command, $return);
1846
-
1847
- if ($string)
1848
- return $log;
1849
-
1850
- if ($rawreturn)
1851
- return $return;
1852
-
1853
- return $return ? false : true;
1854
- } elseif ($this->iwp_mmb_function_exists('passthru') && !$string) {
1855
- $log = passthru($command, $return);
1856
-
1857
- if ($rawreturn)
1858
- return $return;
1859
-
1860
- return $return ? false : true;
1861
- }
1862
-
1863
- if ($rawreturn)
1864
- return -1;
1865
-
1866
- return false;
1867
- }
1868
-
1869
- function get_zip()
1870
- {
1871
- $zip = $this->iwp_mmb_exec('which zip', true);
1872
- if (!$zip)
1873
- $zip = "zip";
1874
- return $zip;
1875
- }
1876
-
1877
- function get_unzip()
1878
- {
1879
- $unzip = $this->iwp_mmb_exec('which unzip', true);
1880
- if (!$unzip)
1881
- $unzip = "unzip";
1882
- return $unzip;
1883
- }
1884
-
1885
- function check_backup_compat()
1886
- {
1887
- $reqs = array();
1888
- if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1889
- $reqs['Server OS']['status'] = 'Linux (or compatible)';
1890
- $reqs['Server OS']['pass'] = true;
1891
- } else {
1892
- $reqs['Server OS']['status'] = 'Windows';
1893
- $reqs['Server OS']['pass'] = true;
1894
- $pass = false;
1895
- }
1896
- $reqs['PHP Version']['status'] = phpversion();
1897
- if ((float) phpversion() >= 5.1) {
1898
- $reqs['PHP Version']['pass'] = true;
1899
- } else {
1900
- $reqs['PHP Version']['pass'] = false;
1901
- $pass = false;
1902
- }
1903
-
1904
-
1905
- if (is_writable(WP_CONTENT_DIR)) {
1906
- $reqs['Backup Folder']['status'] = "writable";
1907
- $reqs['Backup Folder']['pass'] = true;
1908
- } else {
1909
- $reqs['Backup Folder']['status'] = "not writable";
1910
- $reqs['Backup Folder']['pass'] = false;
1911
- }
1912
-
1913
-
1914
- $file_path = IWP_BACKUP_DIR;
1915
- $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1916
-
1917
- if ($func = $this->check_sys()) {
1918
- $reqs['Execute Function']['status'] = $func;
1919
- $reqs['Execute Function']['pass'] = true;
1920
- } else {
1921
- $reqs['Execute Function']['status'] = "not found";
1922
- $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1923
- $reqs['Execute Function']['pass'] = false;
1924
- }
1925
- $reqs['Zip']['status'] = $this->get_zip();
1926
-
1927
- $reqs['Zip']['pass'] = true;
1928
-
1929
-
1930
-
1931
- $reqs['Unzip']['status'] = $this->get_unzip();
1932
-
1933
- $reqs['Unzip']['pass'] = true;
1934
-
1935
- $paths = $this->check_mysql_paths();
1936
-
1937
- if (!empty($paths['mysqldump'])) {
1938
- $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1939
- $reqs['MySQL Dump']['pass'] = true;
1940
- } else {
1941
- $reqs['MySQL Dump']['status'] = "not found";
1942
- $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1943
- $reqs['MySQL Dump']['pass'] = false;
1944
- }
1945
-
1946
- $exec_time = ini_get('max_execution_time');
1947
- $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1948
- $reqs['Execution time']['pass'] = true;
1949
-
1950
- $mem_limit = ini_get('memory_limit');
1951
- $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1952
- $reqs['Memory limit']['pass'] = true;
1953
-
1954
-
1955
- return $reqs;
1956
- }
1957
-
1958
- function ftp_backup($args)
1959
- {
1960
- extract($args);
1961
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1962
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
1963
- if ($ftp_ssl) {
1964
- if (function_exists('ftp_ssl_connect')) {
1965
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1966
- if ($conn_id === false) {
1967
- return array(
1968
- 'error' => 'Failed to connect to ' . $ftp_hostname,
1969
- 'partial' => 1
1970
- );
1971
- }
1972
- } else {
1973
- return array(
1974
- 'error' => 'Your server doesn\'t support FTP SSL',
1975
- 'partial' => 1
1976
- );
1977
- }
1978
- } else {
1979
- if (function_exists('ftp_connect')) {
1980
- $conn_id = ftp_connect($ftp_hostname,$port);
1981
- if ($conn_id === false) {
1982
- return array(
1983
- 'error' => 'Failed to connect to ' . $ftp_hostname,
1984
- 'partial' => 1
1985
- );
1986
- }
1987
- } else {
1988
- return array(
1989
- 'error' => 'Your server doesn\'t support FTP',
1990
- 'partial' => 1
1991
- );
1992
- }
1993
- }
1994
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1995
- if ($login === false) {
1996
- return array(
1997
- 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1998
- 'partial' => 1
1999
- );
2000
- }
2001
-
2002
- if($ftp_passive){
2003
- @ftp_pasv($conn_id,true);
2004
- }
2005
-
2006
- @ftp_mkdir($conn_id, $ftp_remote_folder);
2007
- if ($ftp_site_folder) {
2008
- $ftp_remote_folder .= '/' . $this->site_name;
2009
- }
2010
- @ftp_mkdir($conn_id, $ftp_remote_folder);
2011
-
2012
- $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
2013
-
2014
- if ($upload === false) { //Try ascii
2015
- $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
2016
- }
2017
- @ftp_close($conn_id);
2018
-
2019
- if ($upload === false) {
2020
- return array(
2021
- 'error' => 'Failed to upload file to FTP. Please check your specified path.',
2022
- 'partial' => 1
2023
- );
2024
- }
2025
-
2026
- return true;
2027
- }
2028
-
2029
- function remove_ftp_backup($args)
2030
- {
2031
- extract($args);
2032
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
2033
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
2034
- if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
2035
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
2036
- } else if (function_exists('ftp_connect')) {
2037
- $conn_id = ftp_connect($ftp_hostname,$port);
2038
- }
2039
-
2040
- if ($conn_id) {
2041
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
2042
- if ($ftp_site_folder)
2043
- $ftp_remote_folder .= '/' . $this->site_name;
2044
-
2045
- if($ftp_passive){
2046
- @ftp_pasv($conn_id,true);
2047
- }
2048
-
2049
- $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
2050
-
2051
- ftp_close($conn_id);
2052
- }
2053
-
2054
- }
2055
-
2056
- function get_ftp_backup($args)
2057
- {
2058
- extract($args);
2059
- //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
2060
- $port = $ftp_port ? $ftp_port : 21; //default port is 21
2061
- if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
2062
- $conn_id = ftp_ssl_connect($ftp_hostname,$port);
2063
-
2064
- } else if (function_exists('ftp_connect')) {
2065
- $conn_id = ftp_connect($ftp_hostname,$port);
2066
- if ($conn_id === false) {
2067
- return false;
2068
- }
2069
- }
2070
- $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
2071
- if ($login === false) {
2072
- return false;
2073
- }
2074
-
2075
- if ($ftp_site_folder)
2076
- $ftp_remote_folder .= '/' . $this->site_name;
2077
-
2078
- if($ftp_passive){
2079
- @ftp_pasv($conn_id,true);
2080
- }
2081
-
2082
- //$temp = ABSPATH . 'iwp_temp_backup.zip';
2083
- $temp = wp_tempnam('iwp_temp_backup.zip');
2084
-
2085
- $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
2086
- if ($get === false) {
2087
- return false;
2088
- } else {
2089
- }
2090
- ftp_close($conn_id);
2091
-
2092
- return $temp;
2093
- }
2094
-
2095
-
2096
- function dropbox_backup($args){
2097
- extract($args);
2098
-
2099
- if(isset($consumer_secret) && !empty($consumer_secret)){
2100
-
2101
- require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2102
-
2103
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
2104
- $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2105
-
2106
- if ($dropbox_site_folder == true)
2107
- $dropbox_destination .= '/' . $this->site_name . '/' . basename($backup_file);
2108
- else
2109
- $dropbox_destination .= '/' . basename($backup_file);
2110
-
2111
- try {
2112
- $dropbox->upload($backup_file, $dropbox_destination, true);
2113
- } catch (Exception $e) {
2114
- $this->_log($e->getMessage());
2115
- return array(
2116
- 'error' => $e->getMessage(),
2117
- 'partial' => 1
2118
- );
2119
- }
2120
-
2121
- return true;
2122
-
2123
- } else {
2124
- return array(
2125
- 'error' => 'Please connect your InfiniteWP panel with your Dropbox account.'
2126
- );
2127
- }
2128
-
2129
- }
2130
-
2131
-
2132
- function remove_dropbox_backup($args) {
2133
- extract($args);
2134
-
2135
- require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2136
-
2137
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
2138
- $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2139
-
2140
- if ($dropbox_site_folder == true)
2141
- $dropbox_destination .= '/' . $this->site_name;
2142
-
2143
- try {
2144
- $dropbox->fileopsDelete($dropbox_destination . '/' . $backup_file);
2145
- } catch (Exception $e) {
2146
- $this->_log($e->getMessage());
2147
- /*return array(
2148
- 'error' => $e->getMessage(),
2149
- 'partial' => 1
2150
- );*/
2151
- }
2152
-
2153
- //return true;
2154
- }
2155
-
2156
-
2157
- function get_dropbox_backup($args) {
2158
- extract($args);
2159
-
2160
- require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2161
-
2162
- $dropbox = new Dropbox($consumer_key, $consumer_secret);
2163
- $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2164
-
2165
- if ($dropbox_site_folder == true)
2166
- $dropbox_destination .= '/' . $this->site_name;
2167
-
2168
- //$temp = ABSPATH . 'iwp_temp_backup.zip';
2169
- $temp = wp_tempnam('iwp_temp_backup.zip');
2170
-
2171
- try {
2172
-
2173
- $file = $dropbox->download($dropbox_destination.'/'.$backup_file);
2174
- $handle = @fopen($temp, 'w');
2175
- $result = fwrite($handle, $file);
2176
- fclose($handle);
2177
-
2178
- if($result)
2179
- return $temp;
2180
- else
2181
- return false;
2182
- } catch (Exception $e) {
2183
- $this->_log($e->getMessage());
2184
- return array(
2185
- 'error' => $e->getMessage(),
2186
- 'partial' => 1
2187
- );
2188
- }
2189
- }
2190
-
2191
-
2192
- function amazons3_backup($args)
2193
- {
2194
- if ($this->iwp_mmb_function_exists('curl_init')) {
2195
- require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2196
-
2197
- extract($args);
2198
-
2199
- if ($as3_site_folder == true)
2200
- $as3_directory .= '/' . $this->site_name;
2201
-
2202
- try{
2203
-
2204
- CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true, 'use_ssl'=>false, 'ssl_verification'=>false), '@default' => 'development'));
2205
- $s3 = new AmazonS3();
2206
- $response = $s3->create_object($as3_bucket, $as3_directory . '/' . basename($backup_file), array('fileUpload' => $backup_file));
2207
- $upload = $response->isOk();
2208
- if($upload) {
2209
- return true;
2210
- } else {
2211
- return array(
2212
- 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
2213
- 'partial' => 1
2214
- );
2215
- }
2216
-
2217
- }catch (Exception $e){
2218
- $err = $e->getMessage();
2219
- if($err){
2220
- return array(
2221
- 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
2222
- );
2223
- } else {
2224
- return array(
2225
- 'error' => 'Failed to upload to Amazon S3.'
2226
- );
2227
- }
2228
- }
2229
- } else {
2230
- return array(
2231
- 'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
2232
- 'partial' => 1
2233
- );
2234
- }
2235
- }
2236
-
2237
-
2238
- function remove_amazons3_backup($args)
2239
- {
2240
- if ($this->iwp_mmb_function_exists('curl_init')) {
2241
- require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2242
- extract($args);
2243
- if ($as3_site_folder == true)
2244
- $as3_directory .= '/' . $this->site_name;
2245
- try{
2246
- CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true), '@default' => 'development'));
2247
- $s3 = new AmazonS3();
2248
- $s3->delete_object($as3_bucket, $as3_directory . '/' . $backup_file);
2249
- } catch (Exception $e){
2250
-
2251
- }
2252
- }
2253
- }
2254
-
2255
- function get_amazons3_backup($args)
2256
- {
2257
- require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2258
- extract($args);
2259
- $temp = '';
2260
- try{
2261
- CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true), '@default' => 'development'));
2262
- $s3 = new AmazonS3();
2263
- if ($as3_site_folder == true)
2264
- $as3_directory .= '/' . $this->site_name;
2265
-
2266
- //$temp = ABSPATH . 'iwp_temp_backup.zip';
2267
- $temp = wp_tempnam('iwp_temp_backup.zip');
2268
- $s3->get_object($as3_bucket, $as3_directory . '/' . $backup_file, array("fileDownload" => $temp));
2269
- } catch (Exception $e){
2270
- return $temp;
2271
- }
2272
- return $temp;
2273
- }
2274
- //IWP Remove ends here
2275
-
2276
-
2277
- function schedule_next($type, $schedule)
2278
- {
2279
- $schedule = explode("|", $schedule);
2280
- if (empty($schedule))
2281
- return false;
2282
- switch ($type) {
2283
-
2284
- case 'daily':
2285
-
2286
- if (isset($schedule[1]) && $schedule[1]) {
2287
- $delay_time = $schedule[1] * 60;
2288
- }
2289
-
2290
- $current_hour = date("H");
2291
- $schedule_hour = $schedule[0];
2292
- if ($current_hour >= $schedule_hour){
2293
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
2294
- //$time ='0001#'.$current_hour.'|'.$schedule_hour;
2295
-
2296
- }
2297
-
2298
- else{
2299
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2300
- //$time ='0000#'.$current_hour.'|'.$schedule_hour;
2301
- }
2302
- $time = time() + 30;
2303
-
2304
-
2305
- break;
2306
-
2307
-
2308
- case 'weekly':
2309
- if (isset($schedule[2]) && $schedule[2]) {
2310
- $delay_time = $schedule[2] * 60;
2311
- }
2312
- $current_weekday = date('w');
2313
- $schedule_weekday = $schedule[1];
2314
- $current_hour = date("H");
2315
- $schedule_hour = $schedule[0];
2316
-
2317
- if ($current_weekday > $schedule_weekday)
2318
- $weekday_offset = 7 - ($week_day - $task_schedule[1]);
2319
- else
2320
- $weekday_offset = $schedule_weekday - $current_weekday;
2321
-
2322
-
2323
- if (!$weekday_offset) { //today is scheduled weekday
2324
- if ($current_hour >= $schedule_hour)
2325
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
2326
- else
2327
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2328
- } else {
2329
- $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
2330
- }
2331
-
2332
- break;
2333
-
2334
- case 'monthly':
2335
- if (isset($schedule[2]) && $schedule[2]) {
2336
- $delay_time = $schedule[2] * 60;
2337
- }
2338
- $current_monthday = date('j');
2339
- $schedule_monthday = $schedule[1];
2340
- $current_hour = date("H");
2341
- $schedule_hour = $schedule[0];
2342
-
2343
- if ($current_monthday > $schedule_monthday) {
2344
- $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2345
- } else if ($current_monthday < $schedule_monthday) {
2346
- $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2347
- } else if ($current_monthday == $schedule_monthday) {
2348
- if ($current_hour >= $schedule_hour)
2349
- $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2350
- else
2351
- $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2352
- break;
2353
- }
2354
-
2355
- break;
2356
- default:
2357
- break;
2358
- }
2359
-
2360
- if (isset($delay_time) && $delay_time) {
2361
- $time += $delay_time;
2362
- }
2363
-
2364
- return $time;
2365
- }
2366
-
2367
-
2368
- //Parse task arguments for info on IWP Admin Panel
2369
- function get_backup_stats()
2370
- {
2371
- $stats = array();
2372
- $tasks = $this->tasks;
2373
- if (is_array($tasks) && !empty($tasks)) {
2374
- foreach ($tasks as $task_name => $info) {
2375
- if (is_array($info['task_results']) && !empty($info['task_results'])) {
2376
- foreach ($info['task_results'] as $key => $result) {
2377
- if (isset($result['server']) && !isset($result['error'])) {
2378
- if (!file_exists($result['server']['file_path'])) {
2379
- $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
2380
- }
2381
- }
2382
- }
2383
- }
2384
- if (is_array($info['task_results']))
2385
- $stats[$task_name] = $info['task_results'];
2386
- }
2387
- }
2388
- return $stats;
2389
- }
2390
-
2391
-
2392
- function get_next_schedules()
2393
- {
2394
- $stats = array();
2395
- $tasks = $this->tasks;
2396
- if (is_array($tasks) && !empty($tasks)) {
2397
- foreach ($tasks as $task_name => $info) {
2398
- $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
2399
- }
2400
- }
2401
- return $stats;
2402
- }
2403
-
2404
-
2405
- function remove_old_backups($task_name)
2406
- {
2407
- //Check for previous failed backups first
2408
- $this->cleanup();
2409
-
2410
- //Remove by limit
2411
- $backups = $this->tasks;
2412
- if ($task_name == 'Backup Now') {
2413
- $num = 0;
2414
- } else {
2415
- $num = 1;
2416
- }
2417
-
2418
-
2419
- if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
2420
- //how many to remove ?
2421
- $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
2422
- for ($i = 0; $i < $remove_num; $i++) {
2423
- //Remove from the server
2424
- if (isset($backups[$task_name]['task_results'][$i]['server'])) {
2425
- @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
2426
- }
2427
-
2428
- if (isset($backups[$task_name]['task_results'][$i]['ftp'])) {
2429
- $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
2430
- $args = $backups[$task_name]['task_args']['account_info']['iwp_ftp'];
2431
- $args['backup_file'] = $ftp_file;
2432
- $this->remove_ftp_backup($args);
2433
- }
2434
-
2435
- if (isset($backups[$task_name]['task_results'][$i]['amazons3'])) {
2436
- $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
2437
- $args = $backups[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
2438
- $args['backup_file'] = $amazons3_file;
2439
- $this->remove_amazons3_backup($args);
2440
- }
2441
-
2442
- if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['iwp_dropbox'])) {
2443
- //To do: dropbox remove
2444
- $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
2445
- $args = $backups[$task_name]['task_args']['account_info']['iwp_dropbox'];
2446
- $args['backup_file'] = $dropbox_file;
2447
- $this->remove_dropbox_backup($args);
2448
- }
2449
- //Remove database backup info
2450
- unset($backups[$task_name]['task_results'][$i]);
2451
-
2452
- } //end foreach
2453
-
2454
- if (is_array($backups[$task_name]['task_results']))
2455
- $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
2456
- else
2457
- $backups[$task_name]['task_results']=array();
2458
-
2459
- $this->update_tasks($backups);
2460
-
2461
- return true;
2462
- }
2463
- }
2464
-
2465
- /**
2466
- * Delete specified backup
2467
- * Args: $task_name, $result_id
2468
- */
2469
-
2470
- function delete_backup($args)
2471
- {
2472
- if (empty($args))
2473
- return false;
2474
- extract($args);
2475
-
2476
- $tasks = $this->tasks;
2477
- $task = $tasks[$task_name];
2478
- $backups = $task['task_results'];
2479
- $backup = $backups[$result_id];
2480
-
2481
- if (isset($backup['server'])) {
2482
- @unlink($backup['server']['file_path']);
2483
- }
2484
-
2485
- /*
2486
- //IWP Remove starts here//IWP Remove ends here
2487
- */
2488
- //Remove from ftp
2489
- if (isset($backup['ftp'])) {
2490
- $ftp_file = $backup['ftp'];
2491
- $args = $tasks[$task_name]['task_args']['account_info']['iwp_ftp'];
2492
- $args['backup_file'] = $ftp_file;
2493
- $this->remove_ftp_backup($args);
2494
- }
2495
-
2496
- if (isset($backup['amazons3'])) {
2497
- $amazons3_file = $backup['amazons3'];
2498
- $args = $tasks[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
2499
- $args['backup_file'] = $amazons3_file;
2500
- $this->remove_amazons3_backup($args);
2501
- }
2502
-
2503
- if (isset($backup['dropbox'])) {
2504
- $dropbox_file = $backup['dropbox'];
2505
- $args = $tasks[$task_name]['task_args']['account_info']['iwp_dropbox'];
2506
- $args['backup_file'] = $dropbox_file;
2507
- $this->remove_dropbox_backup($args);
2508
- }
2509
-
2510
-
2511
- unset($backups[$result_id]);
2512
-
2513
- if (count($backups)) {
2514
- $tasks[$task_name]['task_results'] = $backups;
2515
- } else {
2516
- unset($tasks[$task_name]['task_results']);
2517
- }
2518
-
2519
- $this->update_tasks($tasks);
2520
- //update_option('iwp_client_backup_tasks', $tasks);
2521
- return true;
2522
-
2523
- }
2524
-
2525
- function cleanup()
2526
- {
2527
- $tasks = $this->tasks;
2528
- $backup_folder = WP_CONTENT_DIR . '/' . md5('iwp_mmb-client') . '/iwp_backups/';
2529
- $backup_folder_new = IWP_BACKUP_DIR . '/';
2530
- $files = glob($backup_folder . "*");
2531
- $new = glob($backup_folder_new . "*");
2532
-
2533
- //Failed db files first
2534
- $db_folder = IWP_DB_DIR . '/';
2535
- $db_files = glob($db_folder . "*");
2536
- if (is_array($db_files) && !empty($db_files)) {
2537
- foreach ($db_files as $file) {
2538
- @unlink($file);
2539
- }
2540
- @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
2541
- @rmdir(IWP_DB_DIR);
2542
- }
2543
-
2544
-
2545
- //clean_old folder?
2546
- if ((basename($files[0]) == 'index.php' && count($files) == 1) || (!empty($files))) { //USE (!empty($files)
2547
- foreach ($files as $file) {
2548
- @unlink($file);
2549
- }
2550
- @rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client') . '/iwp_backups');
2551
- @rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client'));
2552
- }
2553
-
2554
- if (!empty($new)) {
2555
- foreach ($new as $b) {
2556
- $files[] = $b;
2557
- }
2558
- }
2559
- $deleted = array();
2560
-
2561
- if (is_array($files) && count($files)) {
2562
- $results = array();
2563
- if (!empty($tasks)) {
2564
- foreach ((array) $tasks as $task) {
2565
- if (isset($task['task_results']) && count($task['task_results'])) {
2566
- foreach ($task['task_results'] as $backup) {
2567
- if (isset($backup['server'])) {
2568
- $results[] = $backup['server']['file_path'];
2569
- }
2570
- }
2571
- }
2572
- }
2573
- }
2574
-
2575
- $num_deleted = 0;
2576
- foreach ($files as $file) {
2577
- if (!in_array($file, $results) && basename($file) != 'index.php') {
2578
- @unlink($file);
2579
- $deleted[] = basename($file);
2580
- $num_deleted++;
2581
- }
2582
- }
2583
- }
2584
-
2585
-
2586
-
2587
- return $deleted;
2588
- }
2589
-
2590
-
2591
- /*
2592
- */
2593
-
2594
- function validate_task($args, $url)
2595
- {
2596
- if (!class_exists('WP_Http')) {
2597
- include_once(ABSPATH . WPINC . '/class-http.php');
2598
- }
2599
- $params = array();
2600
- $params['body'] = $args;
2601
- $result = wp_remote_post($url, $params);
2602
- if (is_array($result) && $result['body'] == 'iwp_delete_task') {
2603
- //$tasks = $this->get_backup_settings();
2604
- $tasks = $this->tasks;
2605
- unset($tasks[$args['task_name']]);
2606
- $this->update_tasks($tasks);
2607
- $this->cleanup();
2608
- exit;
2609
- } elseif(is_array($result) && $result['body'] == 'iwp_pause_task'){
2610
- return 'paused';
2611
- }
2612
-
2613
- return 'ok';
2614
- }
2615
-
2616
- function update_status($task_name, $status, $completed = false)
2617
- {
2618
- /* Statuses:
2619
- 0 - Backup started
2620
- 1 - DB dump
2621
- 2 - DB ZIP
2622
- 3 - Files ZIP
2623
- 4 - Amazon S3
2624
- 5 - Dropbox
2625
- 6 - FTP
2626
- 7 - Email
2627
- 100 - Finished
2628
- */
2629
- //if ($task_name != 'Backup Now') {
2630
- $tasks = $this->tasks;
2631
- $index = count($tasks[$task_name]['task_results']) - 1;
2632
- //!is_array($tasks[$task_name]['task_results'][$index]['status']) &&
2633
- if (!is_array($tasks[$task_name]['task_results'][$index]['backhack_status'])) {
2634
- //$tasks[$task_name]['task_results'][$index]['status'] = array();
2635
- $tasks[$task_name]['task_results'][$index]['backhack_status'] = array();
2636
- }
2637
- $tasks[$task_name]['task_results'][$index]['backhack_status']['adminHistoryID'] = $GLOBALS['IWP_CLIENT_HISTORY_ID'];
2638
- if (!$completed) {
2639
- //$tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
2640
- $tasks[$task_name]['task_results'][$index]['backhack_status'][$status]['start'] = microtime(true);
2641
- } else {
2642
- $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
2643
- //$tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
2644
- $tasks[$task_name]['task_results'][$index]['backhack_status'][$status]['end'] = microtime(true);
2645
- }
2646
-
2647
- $this->update_tasks($tasks);
2648
- //update_option('iwp_client_backup_tasks',$tasks);
2649
- //}
2650
- }
2651
-
2652
- function update_tasks($tasks)
2653
- {
2654
- $this->tasks = $tasks;
2655
- update_option('iwp_client_backup_tasks', $tasks);
2656
- }
2657
-
2658
- function wpdb_reconnect(){
2659
- global $wpdb;
2660
- $old_wpdb = $wpdb;
2661
- //Reconnect to avoid timeout problem after ZIP files
2662
- if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
2663
- @mysql_close($wpdb->dbh);
2664
- $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2665
- wp_set_wpdb_vars();
2666
- $wpdb->options = $old_wpdb->options;//fix for multi site full backup
2667
- }
2668
- }
2669
-
2670
- function replace_htaccess($url, $remote_abspath)
2671
- {
2672
- global $wp_filesystem;
2673
- //$file = @file_get_contents(ABSPATH.'.htaccess');
2674
- $file = $wp_filesystem->get_contents($remote_abspath.'.htaccess');
2675
- if ($file && strlen($file)) {
2676
- $args = parse_url($url);
2677
- $string = rtrim($args['path'], "/");
2678
- $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
2679
- $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
2680
- $file = preg_replace($regex, $replace, $file);
2681
- //@file_put_contents(ABSPATH.'.htaccess', $file);
2682
- $wp_filesystem->put_contents($remote_abspath.'.htaccess', $file);
2683
- }
2684
- }
2685
-
2686
- function check_cron_remove(){
2687
- if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
2688
- wp_clear_scheduled_hook('iwp_client_backup_tasks');
2689
- exit;
2690
- }
2691
- }
2692
-
2693
-
2694
- public function readd_tasks( $params = array() ){
2695
- global $iwp_mmb_core;
2696
-
2697
- if( empty($params) || !isset($params['backups']) )
2698
- return $params;
2699
-
2700
- $before = array();
2701
- $tasks = $params['backups'];
2702
- if( !empty($tasks) ){
2703
- $iwp_mmb_backup = new IWP_MMB_Backup();
2704
-
2705
- if( function_exists( 'wp_next_scheduled' ) ){
2706
- if ( !wp_next_scheduled('iwp_client_backup_tasks') ) {
2707
- wp_schedule_event( time(), 'tenminutes', 'iwp_client_backup_tasks' );
2708
- }
2709
- }
2710
-
2711
- foreach( $tasks as $task ){
2712
- $before[$task['task_name']] = array();
2713
-
2714
- if(isset($task['secure'])){
2715
- if($decrypted = $iwp_mmb_core->_secure_data($task['secure'])){
2716
- $decrypted = maybe_unserialize($decrypted);
2717
- if(is_array($decrypted)){
2718
- foreach($decrypted as $key => $val){
2719
- if(!is_numeric($key))
2720
- $task[$key] = $val;
2721
- }
2722
- unset($task['secure']);
2723
- } else
2724
- $task['secure'] = $decrypted;
2725
- }
2726
-
2727
- }
2728
- if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from panel first time(secure data)
2729
- $task['args']['account_info'] = $task['account_info'];
2730
- }
2731
-
2732
- $before[$task['task_name']]['task_args'] = $task['args'];
2733
- $before[$task['task_name']]['task_args']['next'] = $iwp_mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
2734
- }
2735
- }
2736
- update_option('iwp_client_backup_tasks', $before);
2737
-
2738
- unset($params['backups']);
2739
- return $params;
2740
- }
2741
-
2742
- function is_server_writable(){
2743
- if((!defined('FTP_HOST') || !defined('FTP_USER') || !defined('FTP_PASS')) && (get_filesystem_method(array(), ABSPATH) != 'direct'))
2744
- return false;
2745
- else
2746
- return true;
2747
- }
2748
- }
2749
-
2750
- /*if( function_exists('add_filter') ){
2751
- add_filter( 'iwp_website_add', 'IWP_MMB_Backup::readd_tasks' );
2752
- }*/
2753
-
2754
- if(!function_exists('get_all_files_from_dir')) {
2755
- /**
2756
- * Get all files in directory
2757
- *
2758
- * @param string $path Relative or absolute path to folder
2759
- * @param array $exclude List of excluded files or folders, relative to $path
2760
- * @return array List of all files in folder $path, exclude all files in $exclude array
2761
- */
2762
- function get_all_files_from_dir($path, $exclude = array()) {
2763
- if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
2764
- global $directory_tree, $ignore_array;
2765
- $directory_tree = array();
2766
- foreach ($exclude as $file) {
2767
- if (!in_array($file, array('.', '..'))) {
2768
- if ($file[0] === "/") $path = substr($file, 1);
2769
- $ignore_array[] = "$path/$file";
2770
- }
2771
- }
2772
- get_all_files_from_dir_recursive($path);
2773
- return $directory_tree;
2774
- }
2775
- }
2776
-
2777
- if (!function_exists('get_all_files_from_dir_recursive')) {
2778
- /**
2779
- * Get all files in directory,
2780
- * wrapped function which writes in global variable
2781
- * and exclued files or folders are read from global variable
2782
- *
2783
- * @param string $path Relative or absolute path to folder
2784
- * @return void
2785
- */
2786
- function get_all_files_from_dir_recursive($path) {
2787
- if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
2788
- global $directory_tree, $ignore_array;
2789
- $directory_tree_temp = array();
2790
- $dh = @opendir($path);
2791
-
2792
- while (false !== ($file = @readdir($dh))) {
2793
- if (!in_array($file, array('.', '..'))) {
2794
- if (!in_array("$path/$file", $ignore_array)) {
2795
- if (!is_dir("$path/$file")) {
2796
- $directory_tree[] = "$path/$file";
2797
- } else {
2798
- get_all_files_from_dir_recursive("$path/$file");
2799
- }
2800
- }
2801
- }
2802
- }
2803
- @closedir($dh);
2804
- }
2805
- }
2806
-
2807
  ?>
1
+ <?php
2
+ /************************************************************
3
+ * This plugin was modified by Revmakx *
4
+ * Copyright (c) 2012 Revmakx *
5
+ * www.revmakx.com *
6
+ * *
7
+ ************************************************************/
8
+ /*************************************************************
9
+ *
10
+ * backup.class.php
11
+ *
12
+ * Manage Backups
13
+ *
14
+ *
15
+ * Copyright (c) 2011 Prelovac Media
16
+ * www.prelovac.com
17
+ **************************************************************/
18
+ define('IWP_BACKUP_DIR', WP_CONTENT_DIR . '/infinitewp/backups');
19
+ define('IWP_DB_DIR', IWP_BACKUP_DIR . '/iwp_db');
20
+
21
+ $zip_errors = array(
22
+ 'No error',
23
+ 'No error',
24
+ 'Unexpected end of zip file',
25
+ 'A generic error in the zipfile format was detected',
26
+ 'zip was unable to allocate itself memory',
27
+ 'A severe error in the zipfile format was detected',
28
+ 'Entry too large to be split with zipsplit',
29
+ 'Invalid comment format',
30
+ 'zip -T failed or out of memory',
31
+ 'The user aborted zip prematurely',
32
+ 'zip encountered an error while using a temp file. Please check if this domain\'s account has enough disk space.',
33
+ 'Read or seek error',
34
+ 'zip has nothing to do',
35
+ 'Missing or empty zip file',
36
+ 'Error writing to a file. Please check if this domain\'s account has enough disk space.',
37
+ 'zip was unable to create a file to write to',
38
+ 'bad command line parameters',
39
+ 'no error',
40
+ 'zip could not open a specified file to read'
41
+ );
42
+ $unzip_errors = array(
43
+ 'No error',
44
+ 'One or more warning errors were encountered, but processing completed successfully anyway',
45
+ 'A generic error in the zipfile format was detected',
46
+ 'A severe error in the zipfile format was detected.',
47
+ 'unzip was unable to allocate itself memory.',
48
+ 'unzip was unable to allocate memory, or encountered an encryption error',
49
+ 'unzip was unable to allocate memory during decompression to disk',
50
+ 'unzip was unable allocate memory during in-memory decompression',
51
+ 'unused',
52
+ 'The specified zipfiles were not found',
53
+ 'Bad command line parameters',
54
+ 'No matching files were found',
55
+ 50 => 'The disk is (or was) full during extraction',
56
+ 51 => 'The end of the ZIP archive was encountered prematurely.',
57
+ 80 => 'The user aborted unzip prematurely.',
58
+ 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
59
+ 82 => 'No files were found due to bad decryption password(s)'
60
+ );
61
+
62
+
63
+ class IWP_MMB_Backup extends IWP_MMB_Core
64
+ {
65
+ var $site_name;
66
+ var $statuses;
67
+ var $tasks;
68
+ var $s3;
69
+ var $ftp;
70
+ var $dropbox;
71
+ function __construct()
72
+ {
73
+ parent::__construct();
74
+ $this->site_name = str_replace(array(
75
+ "_",
76
+ "/",
77
+ "~"
78
+ ), array(
79
+ "",
80
+ "-",
81
+ "-"
82
+ ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
83
+ $this->statuses = array(
84
+ 'db_dump' => 1,
85
+ 'db_zip' => 2,
86
+ 'files_zip' => 3,
87
+ 'finished' => 100
88
+ );
89
+ $this->tasks = get_option('iwp_client_backup_tasks');
90
+ }
91
+ function set_memory()
92
+ {
93
+ $changed = array('execution_time' => 0, 'memory_limit' => 0);
94
+ @ignore_user_abort(true);
95
+ $memory_limit = trim(ini_get('memory_limit'));
96
+ $last = strtolower(substr($memory_limit, -1));
97
+
98
+ if($last == 'g')
99
+ $memory_limit = ((int) $memory_limit)*1024;
100
+ else if($last == 'm')
101
+ $memory_limit = (int) $memory_limit;
102
+ if($last == 'k')
103
+ $memory_limit = ((int) $memory_limit)/1024;
104
+
105
+ if ( $memory_limit < 384 ) {
106
+ @ini_set('memory_limit', '384M');
107
+ $changed['memory_limit'] = 1;
108
+ }
109
+
110
+ if ( (int) @ini_get('max_execution_time') < 1200 ) {
111
+ @ini_set('max_execution_time', 1200);//twenty minutes
112
+ @set_time_limit(1200);
113
+ $changed['execution_time'] = 1;
114
+ }
115
+
116
+ return $changed;
117
+
118
+ }
119
+ function get_backup_settings()
120
+ {
121
+ $backup_settings = get_option('iwp_client_backup_tasks');
122
+ if (!empty($backup_settings))
123
+ return $backup_settings;
124
+ else
125
+ return false;
126
+ }
127
+
128
+ function set_backup_task($params)
129
+ {
130
+ //$params => [$task_name, $args, $error]
131
+ if (!empty($params)) {
132
+
133
+ //Make sure backup cron job is set
134
+ if (!wp_next_scheduled('iwp_client_backup_tasks')) {
135
+ wp_schedule_event( time(), 'tenminutes', 'iwp_client_backup_tasks' );
136
+ }
137
+
138
+ extract($params);
139
+
140
+ //$before = $this->get_backup_settings();
141
+ $before = $this->tasks;
142
+ if (!$before || empty($before))
143
+ $before = array();
144
+
145
+ if (isset($args['remove'])) {
146
+ unset($before[$task_name]);
147
+ $return = array(
148
+ 'removed' => true
149
+ );
150
+ } else {
151
+
152
+ if (is_array($params['account_info'])) { //only if sends from IWP Admin Panel first time(secure data)
153
+ $args['account_info'] = $account_info;
154
+ }
155
+
156
+ $before[$task_name]['task_args'] = $args;
157
+ //$before[$task_name]['task_args'] = $task_name;
158
+
159
+ /*if (strlen($args['schedule']))
160
+ $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);*///to WP cron
161
+ $before[$task_name]['task_args']['task_name'] = $task_name;
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 (isset($time) && $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'] = (isset($time) && $time) ? $time : time();
180
+ //}
181
+ if (isset($time) && $time) { //This will occur for schedule runtask.
182
+ $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
183
+ }else{
184
+ if($task_name == 'Backup Now')
185
+ $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = time();
186
+ }
187
+
188
+ $this->update_tasks($before);
189
+ //update_option('iwp_client_backup_tasks', $before);
190
+
191
+ if ($task_name == 'Backup Now') {
192
+ $result = $this->backup($args, $task_name);
193
+ $backup_settings = $this->tasks;
194
+
195
+ if (is_array($result) && array_key_exists('error', $result)) {
196
+ $return = $result;
197
+ } else {
198
+ $return = $backup_settings[$task_name];
199
+ }
200
+ }
201
+ return $return;
202
+ }
203
+
204
+
205
+
206
+ return false;
207
+ }
208
+
209
+ //Cron check
210
+ function check_backup_tasks()
211
+ {
212
+
213
+ $this->check_cron_remove();
214
+
215
+ $settings = $this->tasks;
216
+ if (is_array($settings) && !empty($settings)) {
217
+ foreach ($settings as $task_name => $setting) {
218
+
219
+ if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
220
+ //if ($setting['task_args']['next'] && $_GET['force_backup']) {
221
+ if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
222
+ //Check orphan task
223
+ $check_data = array(
224
+ 'task_name' => $task_name,
225
+ 'task_id' => $setting['task_args']['task_id'],
226
+ 'site_key' => $setting['task_args']['site_key']
227
+ );
228
+
229
+ $check = $this->validate_task($check_data, $setting['task_args']['url']);
230
+
231
+ }
232
+
233
+ $update = array(
234
+ 'task_name' => $task_name,
235
+ 'args' => $settings[$task_name]['task_args']
236
+ );
237
+
238
+
239
+ if($check != 'paused'){
240
+ $update['time'] = time();
241
+ }
242
+
243
+ //Update task with next schedule
244
+ $this->set_backup_task($update);
245
+
246
+ if($check == 'paused'){
247
+ continue;
248
+ }
249
+
250
+
251
+ $result = $this->backup($setting['task_args'], $task_name);
252
+ $error = '';
253
+ if (is_array($result) && array_key_exists('error', $result)) {
254
+ $error = $result;
255
+ $this->set_backup_task(array(
256
+ 'task_name' => $task_name,
257
+ 'args' => $settings[$task_name]['task_args'],
258
+ 'error' => $error
259
+ ));
260
+ } else {
261
+ $error = '';
262
+ }
263
+ break; //Only one backup per cron
264
+ }
265
+ }
266
+ }
267
+
268
+ }
269
+
270
+
271
+ function task_now($task_name){
272
+
273
+ $settings = $this->tasks;
274
+ if(!array_key_exists($task_name,$settings)){
275
+ return array('error' => $task_name." does not exist.");
276
+ } else {
277
+ $setting = $settings[$task_name];
278
+ }
279
+
280
+ $this->set_backup_task(array(
281
+ 'task_name' => $task_name,
282
+ 'args' => $settings[$task_name]['task_args'],
283
+ 'time' => time()
284
+ ));
285
+
286
+ //Run backup
287
+ $result = $this->backup($setting['task_args'], $task_name);
288
+
289
+ //Check for error
290
+ if (is_array($result) && array_key_exists('error', $result)) {
291
+ $this->set_backup_task(array(
292
+ 'task_name' => $task_name,
293
+ 'args' => $settings[$task_name]['task_args'],
294
+ 'error' => $result['error']
295
+ ));
296
+ return $result;
297
+ } else {
298
+ return $this->get_backup_stats();
299
+ }
300
+
301
+ }
302
+
303
+ function delete_task_now($task_name){
304
+ $tasks = $this->tasks;
305
+ unset($tasks[$task_name]);
306
+ $this->update_tasks($tasks);
307
+ $this->cleanup();
308
+
309
+ return $task_name;
310
+
311
+ }
312
+
313
+
314
+ /*
315
+ * If Task Name not set then it's manual backup
316
+ * Backup args:
317
+ * type -> db, full
318
+ * what -> daily, weekly, monthly
319
+ * account_info -> ftp, amazons3, dropbox
320
+ * exclude-> array of paths to exclude from backup
321
+ */
322
+
323
+ function backup($args, $task_name = false)
324
+ {
325
+ if (!$args || empty($args))
326
+ return false;
327
+
328
+ extract($args); //extract settings
329
+
330
+ //$adminHistoryID - admin panel history ID for backup task.
331
+
332
+
333
+ //Try increase memory limit and execution time
334
+ $this->set_memory();
335
+
336
+ //Remove old backup(s)
337
+ $removed = $this->remove_old_backups($task_name);
338
+ if (is_array($removed) && isset($removed['error'])) {
339
+ //$error_message = $removed['error'];
340
+ return $removed;
341
+ }
342
+
343
+ $new_file_path = IWP_BACKUP_DIR;
344
+
345
+ if (!file_exists($new_file_path)) {
346
+ if (!mkdir($new_file_path, 0755, true))
347
+ return array(
348
+ 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
349
+ );
350
+ }
351
+
352
+ @file_put_contents($new_file_path . '/index.php', ''); //safe
353
+
354
+ //Prepare .zip file name
355
+ $hash = md5(time());
356
+ $label = $type ? $type : 'manual';
357
+ $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
358
+ $backup_url = WP_CONTENT_URL . '/infinitewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
359
+
360
+ //Optimize tables?
361
+ if (isset($optimize_tables) && !empty($optimize_tables)) {
362
+ $this->optimize_tables();
363
+ }
364
+
365
+ //What to backup - db or full?
366
+ if (trim($what) == 'db') {
367
+ //Take database backup
368
+ $this->update_status($task_name, 'db_dump');
369
+ $GLOBALS['fail_safe_db'] = $this->tasks[$task_name]['task_args']['fail_safe_db'];
370
+
371
+ $db_result = $this->backup_db();
372
+ if ($db_result == false) {
373
+ return array(
374
+ 'error' => 'Failed to backup database.'
375
+ );
376
+ } else if (is_array($db_result) && isset($db_result['error'])) {
377
+ return array(
378
+ 'error' => $db_result['error']
379
+ );
380
+ } else {
381
+ $this->update_status($task_name, 'db_dump', true);
382
+ $this->update_status($task_name, 'db_zip');
383
+
384
+ /*zip_backup_db*/
385
+ $fail_safe_files = $this->tasks[$task_name]['task_args']['fail_safe_files'];
386
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
387
+
388
+ if($fail_safe_files){
389
+ $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
390
+ }
391
+ else{
392
+ $comp_level = $disable_comp ? '-0' : '-1';
393
+ chdir(IWP_BACKUP_DIR);
394
+ $zip = $this->get_zip();
395
+ $command = "$zip -q -r $comp_level $backup_file 'iwp_db'";
396
+ iwp_mmb_print_flush('DB ZIP CMD: Start');
397
+ ob_start();
398
+ $result = $this->iwp_mmb_exec($command);
399
+ ob_get_clean();
400
+ iwp_mmb_print_flush('DB ZIP CMD: End');
401
+ /*zip_backup_db */
402
+ if(!$result){
403
+ $zip_archive_db_result = false;
404
+ if (class_exists("ZipArchive")) {
405
+ $this->_log("DB zip, fallback to ZipArchive");
406
+ iwp_mmb_print_flush('DB ZIP Archive: Start');
407
+ $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
408
+ iwp_mmb_print_flush('DB ZIP Archive: End');
409
+ }
410
+
411
+ if (!$zip_archive_db_result) {
412
+ $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
413
+ }
414
+ }
415
+ }
416
+
417
+ @unlink($db_result);
418
+ @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
419
+ @rmdir(IWP_DB_DIR);
420
+ /*if (!$result) {
421
+ return array(
422
+ 'error' => 'Failed to zip database.'
423
+ );
424
+ }*///commented because of zipArchive
425
+ $this->update_status($task_name, 'db_zip', true);
426
+ }
427
+ } elseif (trim($what) == 'full') {
428
+ $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
429
+ if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
430
+ return array(
431
+ 'error' => $content_backup['error']
432
+ );
433
+ }
434
+ }
435
+
436
+ //Update backup info
437
+ if ($task_name) {
438
+ //backup task (scheduled)
439
+ $backup_settings = $this->tasks;
440
+ $paths = array();
441
+ $size = round(filesize($backup_file) / 1024, 2);
442
+
443
+ if ($size > 1000) {
444
+ $paths['size'] = round($size / 1024, 2) . " MB";//Modified by IWP //Mb => MB
445
+ } else {
446
+ $paths['size'] = $size . 'KB';//Modified by IWP //Kb => KB
447
+ }
448
+
449
+ $paths['backup_name'] = $backup_settings[$task_name]['task_args']['backup_name'];
450
+
451
+ if ($task_name != 'Backup Now') {
452
+ if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
453
+ $paths['server'] = array(
454
+ 'file_path' => $backup_file,
455
+ 'file_url' => $backup_url
456
+ );
457
+ }
458
+ } else {
459
+ $paths['server'] = array(
460
+ 'file_path' => $backup_file,
461
+ 'file_url' => $backup_url
462
+ );
463
+ }
464
+
465
+
466
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_ftp'])) {
467
+ $paths['ftp'] = basename($backup_url);
468
+ }
469
+
470
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_amazon_s3'])) {
471
+ $paths['amazons3'] = basename($backup_url);
472
+ }
473
+
474
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_dropbox'])) {
475
+ $paths['dropbox'] = basename($backup_url);
476
+ }
477
+
478
+ if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_email'])) {
479
+ $paths['email'] = basename($backup_url);
480
+ }
481
+
482
+ $temp = $backup_settings[$task_name]['task_results'];
483
+ $temp = @array_values($temp);
484
+ $paths['time'] = time();
485
+
486
+
487
+ //if ($task_name != 'Backup Now') {
488
+ $paths['backhack_status'] = $temp[count($temp) - 1]['backhack_status'];
489
+ //$paths['status'] = $temp[count($temp) - 1]['status'];
490
+ $temp[count($temp) - 1] = $paths;
491
+
492
+ /*
493
+ } else {
494
+ $temp[count($temp)] = $paths;
495
+ }
496
+ */
497
+
498
+ $backup_settings[$task_name]['task_results'] = $temp;
499
+ $this->update_tasks($backup_settings);
500
+ //update_option('iwp_client_backup_tasks', $backup_settings);
501
+ }
502
+
503
+
504
+ if ($task_name != 'Backup Now') {
505
+
506
+ if (isset($account_info['iwp_ftp']) && !empty($account_info['iwp_ftp'])) {
507
+ $this->update_status($task_name, 'ftp');
508
+ $account_info['iwp_ftp']['backup_file'] = $backup_file;
509
+ iwp_mmb_print_flush('FTP upload: Start');
510
+ $ftp_result = $this->ftp_backup($account_info['iwp_ftp']);
511
+ iwp_mmb_print_flush('FTP upload: End');
512
+ if ($ftp_result !== true && $del_host_file) {
513
+ @unlink($backup_file);
514
+ }
515
+
516
+ if (is_array($ftp_result) && isset($ftp_result['error'])) {
517
+ return $ftp_result;
518
+ }
519
+ $this->wpdb_reconnect();
520
+ $this->update_status($task_name, 'ftp', true);
521
+ }
522
+
523
+ if (isset($account_info['iwp_amazon_s3']) && !empty($account_info['iwp_amazon_s3'])) {
524
+ $this->update_status($task_name, 's3');
525
+ $account_info['iwp_amazon_s3']['backup_file'] = $backup_file;
526
+ iwp_mmb_print_flush('Amazon S3 upload: Start');
527
+ $amazons3_result = $this->amazons3_backup($account_info['iwp_amazon_s3']);
528
+ iwp_mmb_print_flush('Amazon S3 upload: End');
529
+ if ($amazons3_result !== true && $del_host_file) {
530
+ @unlink($backup_file);
531
+ }
532
+ if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
533
+ return $amazons3_result;
534
+ }
535
+ $this->wpdb_reconnect();
536
+ $this->update_status($task_name, 's3', true);
537
+ }
538
+
539
+ if (isset($account_info['iwp_dropbox']) && !empty($account_info['iwp_dropbox'])) {
540
+ $this->update_status($task_name, 'dropbox');
541
+ $account_info['iwp_dropbox']['backup_file'] = $backup_file;
542
+ iwp_mmb_print_flush('Dropbox upload: Start');
543
+ $dropbox_result = $this->dropbox_backup($account_info['iwp_dropbox']);
544
+ iwp_mmb_print_flush('Dropbox upload: End');
545
+ if ($dropbox_result !== true && $del_host_file) {
546
+ @unlink($backup_file);
547
+ }
548
+
549
+ if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
550
+ return $dropbox_result;
551
+ }
552
+ $this->wpdb_reconnect();
553
+ $this->update_status($task_name, 'dropbox', true);
554
+ }
555
+
556
+ if ($del_host_file) {
557
+ @unlink($backup_file);
558
+ }
559
+
560
+ } //end additional
561
+
562
+ $this->update_status($task_name,'finished',true);
563
+
564
+ return $backup_url; //Return url to backup file
565
+ }
566
+
567
+
568
+ function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
569
+ {
570
+
571
+ global $zip_errors;
572
+ $sys = substr(PHP_OS, 0, 3);
573
+
574
+ $this->update_status($task_name, 'db_dump');
575
+ $GLOBALS['fail_safe_db'] = $this->tasks[$task_name]['task_args']['fail_safe_db'];
576
+ $db_result = $this->backup_db();
577
+
578
+ if ($db_result == false) {
579
+ return array(
580
+ 'error' => 'Failed to backup database.'
581
+ );
582
+ } else if (is_array($db_result) && isset($db_result['error'])) {
583
+ return array(
584
+ 'error' => $db_result['error']
585
+ );
586
+ }
587
+
588
+ $this->update_status($task_name, 'db_dump', true);
589
+ $this->update_status($task_name, 'db_zip');
590
+
591
+ /*zip_backup_db*/
592
+ $fail_safe_files = $this->tasks[$task_name]['task_args']['fail_safe_files'];
593
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
594
+
595
+ if($fail_safe_files){
596
+ $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
597
+ }
598
+ else{
599
+ $comp_level = $disable_comp ? '-0' : '-1';
600
+ $zip = $this->get_zip();
601
+ iwp_mmb_print_flush('DB ZIP CMD: Start');
602
+ //Add database file
603
+ chdir(IWP_BACKUP_DIR);
604
+ $command = "$zip -q -r $comp_level $backup_file 'iwp_db'";
605
+ ob_start();
606
+ $result = $this->iwp_mmb_exec($command);
607
+ ob_get_clean();
608
+ iwp_mmb_print_flush('DB ZIP CMD: End');
609
+ /*zip_backup_db*/
610
+
611
+ if(!$result){
612
+ $zip_archive_db_result = false;
613
+ if (class_exists("ZipArchive")) {
614
+ iwp_mmb_print_flush('DB ZIP Archive: Start');
615
+ $this->_log("DB zip, fallback to ZipArchive");
616
+ $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
617
+ iwp_mmb_print_flush('DB ZIP Archive: End');
618
+ }
619
+
620
+ if (!$zip_archive_db_result) {
621
+ $this->fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp);
622
+ }
623
+ }
624
+ }
625
+ @unlink($db_result);
626
+ @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
627
+ @rmdir(IWP_DB_DIR);
628
+
629
+ $this->update_status($task_name, 'db_zip', true);
630
+
631
+
632
+ //Always remove backup folders
633
+ $remove = array(
634
+ trim(basename(WP_CONTENT_DIR)) . "/infinitewp/backups",
635
+ trim(basename(WP_CONTENT_DIR)) . "/" . md5('iwp_mmb-client') . "/iwp_backups",
636
+ trim(basename(WP_CONTENT_DIR)) . "/cache",
637
+ trim(basename(WP_CONTENT_DIR)) . "/w3tc"
638
+ );
639
+
640
+ $exclude = array_merge($exclude, $remove);
641
+
642
+ //Exclude paths
643
+ $exclude_data = "-x";
644
+
645
+ $exclude_file_data = '';
646
+
647
+ if (!empty($exclude) && is_array($exclude)) {
648
+ foreach ($exclude as $data) {
649
+ if(empty($data))
650
+ continue;
651
+ if (is_dir(ABSPATH . $data)) {
652
+ if ($sys == 'WIN')
653
+ $exclude_data .= " $data/*.*";
654
+ else
655
+ $exclude_data .= " '$data/*'";
656
+ }else {
657
+ if ($sys == 'WIN'){
658
+ if(file_exists(ABSPATH . $data)){
659
+ $exclude_data .= " $data";
660
+ $exclude_file_data .= " $data";
661
+ }
662
+ }else {
663
+ if(file_exists(ABSPATH . $data)){
664
+ $exclude_data .= " '$data'";
665
+ $exclude_file_data .= " '$data'";
666
+ }
667
+ }
668
+ }
669
+ }
670
+ }
671
+
672
+ if($exclude_file_data){
673
+ $exclude_file_data = "-x".$exclude_file_data;
674
+ }
675
+
676
+ /* foreach ($remove as $data) {
677
+ if(empty($data))
678
+ continue;
679
+ if ($sys == 'WIN')
680
+ $exclude_data .= " $data/*.*";
681
+ else
682
+ $exclude_data .= " '$data/*'";
683
+ }*/ //commented for pclzip modifications
684
+
685
+ //Include paths by default
686
+ $add = array(
687
+ trim(WPINC),
688
+ trim(basename(WP_CONTENT_DIR)),
689
+ "wp-admin"
690
+ );
691
+
692
+ $include_data = ". -i";
693
+ foreach ($add as $data) {
694
+ if ($sys == 'WIN')
695
+ $include_data .= " $data/*.*";
696
+ else
697
+ $include_data .= " '$data/*'";
698
+ }
699
+
700
+ //Additional includes?
701
+ if (!empty($include) && is_array($include)) {
702
+ foreach ($include as $data) {
703
+ if(empty($data))
704
+ continue;
705
+ if ($data) {
706
+ if ($sys == 'WIN')
707
+ $include_data .= " $data/*.*";
708
+ else
709
+ $include_data .= " '$data/*'";
710
+ }
711
+ }
712
+ }
713
+
714
+ $this->update_status($task_name, 'files_zip');
715
+ chdir(ABSPATH);
716
+
717
+ if($fail_safe_files){
718
+ $this->fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove);
719
+ }
720
+ else{
721
+ $do_cmd_zip_alternative = false;
722
+ @copy($backup_file, $backup_file.'_2');
723
+
724
+ iwp_mmb_print_flush('Files ZIP CMD: Start');
725
+ $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
726
+ ob_start();
727
+ $result_f = $this->iwp_mmb_exec($command, false, true);
728
+ ob_get_clean();
729
+ iwp_mmb_print_flush('Files ZIP CMD: 1/2 over');
730
+ if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
731
+ $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
732
+ ob_start();
733
+ $result_d = $this->iwp_mmb_exec($command, false, true);
734
+ ob_get_clean();
735
+ if ($result_d && $result_d != 18) {
736
+ @unlink($backup_file);
737
+ $do_cmd_zip_alternative = true;
738
+
739
+
740
+ if($result_d > 0 && $result_d < 18){
741
+ //return array(
742
+ // 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
743
+ // );
744
+ iwp_mmb_print_flush('Files ZIP CMD: Failed to archive files (' . $zip_errors[$result_d] . ') .');
745
+ }
746
+ else{
747
+ //return array(
748
+ // 'error' => 'Failed to archive files.'
749
+ //);
750
+ iwp_mmb_print_flush('Files ZIP CMD: Failed to archive files.');
751
+ }
752
+ }
753
+ }
754
+
755
+ if(!$do_cmd_zip_alternative){//if FILE ZIP CMD successful
756
+ @unlink($backup_file.'_2');
757
+ }
758
+
759
+ iwp_mmb_print_flush('Files ZIP CMD: End');
760
+ if (($result_f && $result_f != 18) || ($do_cmd_zip_alternative)) {
761
+
762
+ if($do_cmd_zip_alternative){
763
+ @copy($backup_file.'_2', $backup_file);
764
+ @unlink($backup_file.'_2');
765
+ }
766
+
767
+ $zip_archive_result = false;
768
+ if (class_exists("ZipArchive")) {
769
+ iwp_mmb_print_flush('Files ZIP Archive: Start');
770
+ $this->_log("Files zip fallback to ZipArchive");
771
+ $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
772
+ iwp_mmb_print_flush('Files ZIP Archive: End');
773
+ }
774
+
775
+
776
+ if (!$zip_archive_result) {
777
+ $this->fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove);
778
+ }
779
+ }
780
+ }
781
+
782
+ //Reconnect
783
+ $this->wpdb_reconnect();
784
+
785
+ $this->update_status($task_name, 'files_zip', true);
786
+ return true;
787
+ }
788
+
789
+
790
+ function fail_safe_pcl_files($task_name, $backup_file, $exclude, $include, $fail_safe_files, $disable_comp, $add, $remove){ //Try pclZip
791
+ //$this->back_hack($task_name, 'Files ZIP PCL: Start');
792
+ iwp_mmb_print_flush('Files ZIP PCL: Start');
793
+ if (!isset($archive)) {
794
+ define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
795
+ //require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
796
+ require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
797
+ $archive = new IWPPclZip($backup_file);
798
+ }
799
+
800
+ //Include paths
801
+ $include_data = array();
802
+ if (!empty($include) && is_array($include)) {
803
+ foreach ($include as $data) {
804
+ if ($data && file_exists(ABSPATH . $data))
805
+ $include_data[] = ABSPATH . $data . '/';
806
+ }
807
+ }
808
+
809
+ foreach ($add as $data) {
810
+ if (file_exists(ABSPATH . $data))
811
+ $include_data[] = ABSPATH . $data . '/';
812
+ }
813
+
814
+ //Include root files
815
+ if ($handle = opendir(ABSPATH)) {
816
+ while (false !== ($file = readdir($handle))) {
817
+ if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
818
+ $include_data[] = ABSPATH . $file;
819
+ }
820
+ }
821
+ closedir($handle);
822
+ }
823
+
824
+ //exclude paths
825
+ $exclude_data = array();
826
+ if (!empty($exclude) && is_array($exclude)) {
827
+ foreach ($exclude as $data) {
828
+ if (is_dir(ABSPATH . $data))
829
+ $exclude_data[] = $data . '/';
830
+ else
831
+ $exclude_data[] = $data;
832
+ }
833
+ }
834
+
835
+ foreach ($remove as $rem) {
836
+ $exclude_data[] = $rem . '/';
837
+ }
838
+
839
+ if($fail_safe_files && $disable_comp){
840
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_NO_COMPRESSION, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
841
+ }
842
+ elseif(!$fail_safe_files && $disable_comp){
843
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_NO_COMPRESSION);
844
+ }
845
+ elseif($fail_safe_files && !$disable_comp){
846
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
847
+ }
848
+ else{
849
+ $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_IWP_EXCLUDE, $exclude_data);
850
+ }
851
+
852
+ iwp_mmb_print_flush('Files ZIP PCL: End');
853
+
854
+ if (!$result) {
855
+ @unlink($backup_file);
856
+ return array(
857
+ 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
858
+ );
859
+ }
860
+ //}
861
+ }
862
+ //Reconnect
863
+ function fail_safe_pcl_db($backup_file,$fail_safe_files,$disable_comp){
864
+ //$this->back_hack($task_name, 'DB ZIP PCL: Start');
865
+ iwp_mmb_print_flush('DB ZIP PCL: Start');
866
+ define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
867
+ require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
868
+ $archive = new IWPPclZip($backup_file);
869
+
870
+ if($fail_safe_files && $disable_comp){
871
+ $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
872
+ }
873
+ elseif(!$fail_safe_files && $disable_comp){
874
+ $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
875
+ }
876
+ elseif($fail_safe_files && !$disable_comp){
877
+ $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
878
+ }
879
+ else{
880
+ $result_db = $archive->add(IWP_DB_DIR, PCLZIP_OPT_REMOVE_PATH, IWP_BACKUP_DIR);
881
+ }
882
+ //$this->back_hack($task_name, 'DB ZIP PCL: End');
883
+ iwp_mmb_print_flush('DB ZIP PCL: End');
884
+
885
+ @unlink($db_result);
886
+ @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
887
+ @rmdir(IWP_DB_DIR);
888
+
889
+ if (!$result_db) {
890
+ return array(
891
+ 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
892
+ );
893
+ }
894
+ }
895
+ /**
896
+ * Zipping database dump and index.php in folder iwp_db by ZipArchive class, requires php zip extension.
897
+ *
898
+ * @param string $task_name the name of backup task
899
+ * @param string $db_result relative path to database dump file
900
+ * @param string $backup_file absolute path to zip file
901
+ * @return bool is compress successful or not
902
+ */
903
+ function zip_archive_backup_db($task_name, $db_result, $backup_file) {
904
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
905
+ if (!$disable_comp) {
906
+ $this->_log("Compression is not supported by ZipArchive");
907
+ }
908
+ $zip = new ZipArchive();
909
+ $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
910
+ if ($result === true) {
911
+ $result = $result && $zip->addFile(IWP_BACKUP_DIR.'/iwp_db/index.php', "iwp_db/index.php"); // Tries to add iwp_db/index.php to $backup_file
912
+ $result = $result && $zip->addFile($db_result, "iwp_db/" . basename($db_result)); // Tries to add db dump form iwp_db dir to $backup_file
913
+ $result = $result && $zip->close(); // Tries to close $backup_file
914
+ } else {
915
+ $result = false;
916
+ }
917
+
918
+ return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
919
+ }
920
+
921
+ /**
922
+ * Zipping whole site root folder and append to backup file with database dump
923
+ * by ZipArchive class, requires php zip extension.
924
+ *
925
+ * @param string $task_name the name of backup task
926
+ * @param string $backup_file absolute path to zip file
927
+ * @param array $exclude array of files of folders to exclude, relative to site's root
928
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
929
+ * @return array|bool true if successful or an array with error message if not
930
+ */
931
+ function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
932
+
933
+ $filelist = $this->get_backup_files($exclude, $include);
934
+ $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
935
+ if (!$disable_comp) {
936
+ $this->_log("Compression is not supported by ZipArchive");
937
+ }
938
+ $zip = new ZipArchive();
939
+ if ($overwrite) {
940
+ $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
941
+ } else {
942
+ $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
943
+ }
944
+ if ($result === true) {
945
+ foreach ($filelist as $file) {
946
+ iwp_mmb_auto_print('zip_archive_backup');
947
+ $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
948
+ }
949
+ $result = $result && $zip->close(); // Tries to close $backup_file
950
+ } else {
951
+ $result = false;
952
+ }
953
+ return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
954
+ }
955
+
956
+
957
+ /**
958
+ * Gets an array of relative paths of all files in site root recursively.
959
+ * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
960
+ * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
961
+ *
962
+ * @param array $exclude array of files of folders to exclude, relative to site's root
963
+ * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
964
+ * @return array array with all files in site root dir
965
+ */
966
+ function get_backup_files($exclude, $include) {
967
+
968
+ $add = array(
969
+ trim(WPINC),
970
+ trim(basename(WP_CONTENT_DIR)),
971
+ "wp-admin"
972
+ );
973
+
974
+ $include = array_merge($add, $include);
975
+
976
+ $filelist = array();
977
+ if ($handle = opendir(ABSPATH)) {
978
+ while (false !== ($file = readdir($handle))) {
979
+ if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
980
+ $exclude[] = $file;
981
+ }
982
+ }
983
+ closedir($handle);
984
+ }
985
+
986
+ $filelist = get_all_files_from_dir(ABSPATH, $exclude);
987
+
988
+ return $filelist;
989
+ }
990
+
991
+
992
+ function backup_db()
993
+ {
994
+ $db_folder = IWP_DB_DIR . '/';
995
+ if (!file_exists($db_folder)) {
996
+ if (!mkdir($db_folder, 0755, true))
997
+ return array(
998
+ 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
999
+ );
1000
+ $db_index_file = '<?php
1001
+ global $old_url, $old_file_path;
1002
+ $old_url = \''.get_option('siteurl').'\';
1003
+ $old_file_path = \''.ABSPATH.'\';
1004
+ ';
1005
+ @file_put_contents(IWP_BACKUP_DIR.'/iwp_db/index.php', $db_index_file);
1006
+ }
1007
+
1008
+ $file = $db_folder . DB_NAME . '.sql';
1009
+
1010
+ if($GLOBALS['fail_safe_db']){
1011
+ $result = $this->backup_db_php($file);
1012
+ return $result;
1013
+ }
1014
+
1015
+ $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
1016
+ return $result;
1017
+ }
1018
+
1019
+ function backup_db_dump($file)
1020
+ {
1021
+ global $wpdb;
1022
+ $paths = $this->check_mysql_paths();
1023
+ $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1024
+ $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;
1025
+ iwp_mmb_print_flush('DB DUMP CMD: Start');
1026
+ ob_start();
1027
+ $result = $this->iwp_mmb_exec($command);
1028
+ ob_get_clean();
1029
+ iwp_mmb_print_flush('DB DUMP CMD: End');
1030
+
1031
+ if (!$result) { // Fallback to php
1032
+ $result = $this->backup_db_php($file);
1033
+ return $result;
1034
+ }
1035
+
1036
+ if (filesize($file) == 0 || !is_file($file) || !$result) {
1037
+ @unlink($file);
1038
+ return false;
1039
+ } else {
1040
+ return $file;
1041
+ }
1042
+ }
1043
+
1044
+ function backup_db_php($file)
1045
+ {
1046
+ global $wpdb;
1047
+
1048
+ if(empty($GLOBALS['fail_safe_db'])){
1049
+ iwp_mmb_print_flush('DB DUMP PHP Normal: Start');
1050
+ $fp = fopen( $file, 'w' );
1051
+ if ( !mysql_ping( $wpdb->dbh ) ) {
1052
+ mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
1053
+ mysql_select_db( DB_NAME );
1054
+ }
1055
+ $_count = 0;
1056
+ $insert_sql = '';
1057
+ $result = mysql_query( 'SHOW TABLES' );
1058
+ if(!$result)
1059
+ {
1060
+ return array(
1061
+ 'error' => 'MySQL '.mysql_error()." "
1062
+ );
1063
+ }
1064
+ while( $row = mysql_fetch_row( $result ) ) {
1065
+ $tables[]=$row[0];
1066
+ //array_push( $tables, $row[0] );
1067
+ }
1068
+
1069
+
1070
+ //$tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1071
+ foreach ($tables as $table) {
1072
+ iwp_mmb_auto_print('backup_db_php_normal');
1073
+
1074
+ $insert_sql .= "DROP TABLE IF EXISTS $table;";
1075
+ //create table
1076
+ $table_descr_query = mysql_query("SHOW CREATE TABLE `$table`");
1077
+ $fetch_table_descr_row = mysql_fetch_array( $table_descr_query );
1078
+ $insert_sql .= "\n\n" . $fetch_table_descr_row[1] . ";\n\n";
1079
+
1080
+ fwrite( $fp, $insert_sql );
1081
+ $insert_sql = '';
1082
+
1083
+ $table_query = mysql_query("SELECT * FROM `$table`");
1084
+ $num_fields = mysql_num_fields($table_query);
1085
+ while ( $fetch_row = mysql_fetch_array( $table_query ) ) {
1086
+ $insert_sql .= "INSERT INTO $table VALUES(";
1087
+ for ( $n=1; $n<=$num_fields; $n++ ) {
1088
+ $m = $n - 1;
1089
+
1090
+ if ( $fetch_row[$m] === NULL ) {
1091
+ $insert_sql .= "NULL, ";
1092
+ } else {
1093
+ $insert_sql .= "'" . mysql_real_escape_string( $fetch_row[$m] ) . "', ";
1094
+ }
1095
+ }
1096
+ $insert_sql = substr( $insert_sql, 0, -2 );
1097
+ $insert_sql .= ");\n";
1098
+
1099
+ fwrite( $fp, $insert_sql );
1100
+ $insert_sql = '';
1101
+
1102
+ // Help keep HTTP alive.
1103
+ $_count++;
1104
+ if ($_count >= 400) {
1105
+ echo ' ';
1106
+ flush();
1107
+ $_count = 0;
1108
+ }
1109
+ } // End foreach $tables.
1110
+
1111
+ $insert_sql .= "\n\n\n";
1112
+
1113
+ // testing: mysql_close( $wpdb->dbh );
1114
+ // Verify database is still connected and working properly. Sometimes mysql runs out of memory and dies in the above foreach.
1115
+ // No point in reconnecting as we can NOT trust that our dump was succesful anymore (it most likely was not).
1116
+ if ( @mysql_ping( $wpdb->dbh ) ) { // Still connected to database.
1117
+ mysql_free_result( $table_query ); // Free memory.
1118
+ } /*else { // Database not connected.
1119
+
1120
+ return false;
1121
+ }*/
1122
+
1123
+ // Help keep HTTP alive.
1124
+ echo ' ';
1125
+ flush();
1126
+
1127
+ //unset( $tables[$table_key] );
1128
+ }
1129
+ fclose( $fp );
1130
+ unset ($fp);
1131
+ iwp_mmb_print_flush('DB DUMP PHP Normal: End');
1132
+ }
1133
+ else{
1134
+ iwp_mmb_print_flush('DB DUMP PHP Fail-safe: Start');
1135
+ file_put_contents($file, '');//safe to reset any old data
1136
+ $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1137
+ foreach ($tables as $table) {
1138
+
1139
+ //drop existing table
1140
+ $dump_data = "DROP TABLE IF EXISTS $table[0];";
1141
+ file_put_contents($file, $dump_data, FILE_APPEND);
1142
+ //create table
1143
+ $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
1144
+ $dump_data = "\n\n" . $create_table[1] . ";\n\n";
1145
+ file_put_contents($file, $dump_data, FILE_APPEND);
1146
+
1147
+ $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
1148
+ if ($count > 100)
1149
+ $count = ceil($count / 100);
1150
+ else if ($count > 0)
1151
+ $count = 1;
1152
+
1153
+ for ($i = 0; $i < $count; $i++) {
1154
+ iwp_mmb_auto_print('backup_db_php_fail_safe');
1155
+ $low_limit = $i * 100;
1156
+ $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
1157
+ $rows = $wpdb->get_results($qry, ARRAY_A);
1158
+ if (is_array($rows)) {
1159
+ foreach ($rows as $row) {
1160
+ //insert single row
1161
+ $dump_data = "INSERT INTO $table[0] VALUES(";
1162
+ $num_values = count($row);
1163
+ $j = 1;
1164
+ foreach ($row as $value) {
1165
+ $value = addslashes($value);
1166
+ $value = preg_replace("/\n/Ui", "\\n", $value);
1167
+ $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
1168
+ $j++;
1169
+ unset($value);
1170
+ }
1171
+ $dump_data .= ");\n";
1172
+ file_put_contents($file, $dump_data, FILE_APPEND);
1173
+ }
1174
+ }
1175
+ }
1176
+ $dump_data = "\n\n\n";
1177
+ file_put_contents($file, $dump_data, FILE_APPEND);
1178
+
1179
+ unset($rows);
1180
+ unset($dump_data);
1181
+ }
1182
+ iwp_mmb_print_flush('DB DUMP PHP Fail-safe: End');
1183
+ }
1184
+
1185
+ if (filesize($file) == 0 || !is_file($file)) {
1186
+ @unlink($file);
1187
+ return array(
1188
+ 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
1189
+ );
1190
+ }
1191
+
1192
+ return $file;
1193
+
1194
+ }
1195
+
1196
+ /**
1197
+ * Copies a directory from one location to another via the WordPress Filesystem Abstraction.
1198
+ * Assumes that WP_Filesystem() has already been called and setup.
1199
+ *
1200
+ * @since 2.5.0
1201
+ *
1202
+ * @param string $from source directory
1203
+ * @param string $to destination directory
1204
+ * @param array $skip_list a list of files/folders to skip copying
1205
+ * @return mixed WP_Error on failure, True on success.
1206
+ */
1207
+ function iwp_mmb_direct_to_any_copy_dir($from, $to, $skip_list = array() ) {//$from => direct file system, $to => automatic filesystem
1208
+ global $wp_filesystem;
1209
+
1210
+ $wp_temp_direct = new WP_Filesystem_Direct('');
1211
+
1212
+
1213
+ $dirlist = $wp_temp_direct->dirlist($from);
1214
+
1215
+ $from = trailingslashit($from);
1216
+ $to = trailingslashit($to);
1217
+
1218
+ $skip_regex = '';
1219
+ foreach ( (array)$skip_list as $key => $skip_file )
1220
+ $skip_regex .= preg_quote($skip_file, '!') . '|';
1221
+
1222
+ if ( !empty($skip_regex) )
1223
+ $skip_regex = '!(' . rtrim($skip_regex, '|') . ')$!i';
1224
+
1225
+ foreach ( (array) $dirlist as $filename => $fileinfo ) {
1226
+ if ( !empty($skip_regex) )
1227
+ if ( preg_match($skip_regex, $from . $filename) )
1228
+ continue;
1229
+
1230
+ if ( 'f' == $fileinfo['type'] ) {
1231
+ if ( ! $this->iwp_mmb_direct_to_any_copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) {
1232
+ // If copy failed, chmod file to 0644 and try again.
1233
+ $wp_filesystem->chmod($to . $filename, 0644);
1234
+ if ( ! $this->iwp_mmb_direct_to_any_copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) )
1235
+ return new WP_Error('copy_failed', __('Could not copy file.'), $to . $filename);
1236
+ }
1237
+ } elseif ( 'd' == $fileinfo['type'] ) {
1238
+ if ( !$wp_filesystem->is_dir($to . $filename) ) {
1239
+ if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) )
1240
+ return new WP_Error('mkdir_failed', __('Could not create directory.'), $to . $filename);
1241
+ }
1242
+ $result = $this->iwp_mmb_direct_to_any_copy_dir($from . $filename, $to . $filename, $skip_list);
1243
+ if ( is_wp_error($result) )
1244
+ return $result;
1245
+ }
1246
+ }
1247
+ return true;
1248
+ }
1249
+
1250
+ function iwp_mmb_direct_to_any_copy($source, $destination, $overwrite = false, $mode = false){
1251
+ global $wp_filesystem;
1252
+ if($wp_filesystem->method == 'direct'){
1253
+ return $wp_filesystem->copy($source, $destination, $overwrite, $mode);
1254
+ }
1255
+ elseif($wp_filesystem->method == 'ftpext' || $wp_filesystem->method == 'ftpsockets'){
1256
+ if ( ! $overwrite && $wp_filesystem->exists($destination) )
1257
+ return false;
1258
+ //$content = $this->get_contents($source);
1259
+ // if ( false === $content)
1260
+ // return false;
1261
+
1262
+ //put content
1263
+ //$tempfile = wp_tempnam($file);
1264
+ $source_handle = fopen($source, 'r');
1265
+ if ( ! $source_handle )
1266
+ return false;
1267
+
1268
+ //fwrite($temp, $contents);
1269
+ //fseek($temp, 0); //Skip back to the start of the file being written to
1270
+
1271
+ $sample_content = fread($source_handle, (1024 * 1024 * 2));//1024 * 1024 * 2 => 2MB
1272
+ fseek($source_handle, 0); //Skip back to the start of the file being written to
1273
+
1274
+ $type = $wp_filesystem->is_binary($sample_content) ? FTP_BINARY : FTP_ASCII;
1275
+ unset($sample_content);
1276
+ if($wp_filesystem->method == 'ftpext'){
1277
+ $ret = @ftp_fput($wp_filesystem->link, $destination, $source_handle, $type);
1278
+ }
1279
+ elseif($wp_filesystem->method == 'ftpsockets'){
1280
+ $wp_filesystem->ftp->SetType($type);
1281
+ $ret = $wp_filesystem->ftp->fput($destination, $source_handle);
1282
+ }
1283
+
1284
+ fclose($source_handle);
1285
+ unlink($source);//to immediately save system space
1286
+ //unlink($tempfile);
1287
+
1288
+ $wp_filesystem->chmod($destination, $mode);
1289
+
1290
+ return $ret;
1291
+
1292
+ //return $this->put_contents($destination, $content, $mode);
1293
+ }
1294
+ }
1295
+
1296
+
1297
+ function restore($args)
1298
+ {
1299
+
1300
+ global $wpdb, $wp_filesystem;
1301
+ if (empty($args)) {
1302
+ return false;
1303
+ }
1304
+
1305
+ extract($args);
1306
+ $this->set_memory();
1307
+
1308
+ $unlink_file = true; //Delete file after restore
1309
+
1310
+ include_once ABSPATH . 'wp-admin/includes/file.php';
1311
+
1312
+ //Detect source
1313
+ if ($backup_url) {
1314
+ //This is for clone (overwrite)
1315
+
1316
+ $backup_file = download_url($backup_url);
1317
+ if (is_wp_error($backup_file)) {
1318
+ return array(
1319
+ 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
1320
+ );
1321
+ }
1322
+ $what = 'full';
1323
+ } else {
1324
+ $tasks = $this->tasks;
1325
+ $task = $tasks[$task_name];
1326
+ if (isset($task['task_results'][$result_id]['server'])) {
1327
+ $backup_file = $task['task_results'][$result_id]['server']['file_path'];
1328
+ $unlink_file = false; //Don't delete file if stored on server
1329
+
1330
+ } elseif (isset($task['task_results'][$result_id]['ftp'])) {
1331
+ $ftp_file = $task['task_results'][$result_id]['ftp'];
1332
+ $args = $task['task_args']['account_info']['iwp_ftp'];
1333
+ $args['backup_file'] = $ftp_file;
1334
+ iwp_mmb_print_flush('FTP download: Start');
1335
+ $backup_file = $this->get_ftp_backup($args);
1336
+ iwp_mmb_print_flush('FTP download: End');
1337
+ if ($backup_file == false) {
1338
+ return array(
1339
+ 'error' => 'Failed to download file from FTP.'
1340
+ );
1341
+ }
1342
+ } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
1343
+ $amazons3_file = $task['task_results'][$result_id]['amazons3'];
1344
+ $args = $task['task_args']['account_info']['iwp_amazon_s3'];
1345
+ $args['backup_file'] = $amazons3_file;
1346
+ iwp_mmb_print_flush('Amazon S3 download: Start');
1347
+ $backup_file = $this->get_amazons3_backup($args);
1348
+ iwp_mmb_print_flush('Amazon S3 download: End');
1349
+ if ($backup_file == false) {
1350
+ return array(
1351
+ 'error' => 'Failed to download file from Amazon S3.'
1352
+ );
1353
+ }
1354
+ } elseif(isset($task['task_results'][$result_id]['dropbox'])){
1355
+ $dropbox_file = $task['task_results'][$result_id]['dropbox'];
1356
+ $args = $task['task_args']['account_info']['iwp_dropbox'];
1357
+ $args['backup_file'] = $dropbox_file;
1358
+ iwp_mmb_print_flush('Dropbox download: Start');
1359
+ $backup_file = $this->get_dropbox_backup($args);
1360
+ iwp_mmb_print_flush('Dropbox download: End');
1361
+
1362
+ if ($backup_file == false) {
1363
+ return array(
1364
+ 'error' => 'Failed to download file from Dropbox.'
1365
+ );
1366
+ }
1367
+ }
1368
+
1369
+
1370
+ $what = $tasks[$task_name]['task_args']['what'];
1371
+ }
1372
+
1373
+
1374
+
1375
+ $this->wpdb_reconnect();
1376
+
1377
+ /////////////////// dev ////////////////////////
1378
+
1379
+
1380
+ if (!$this->is_server_writable()) {
1381
+ return array(
1382
+ 'error' => 'Failed, please add FTP details'
1383
+ );
1384
+ }
1385
+
1386
+ $url = wp_nonce_url('index.php?page=iwp_no_page','iwp_fs_cred');
1387
+ ob_start();
1388
+ if (false === ($creds = request_filesystem_credentials($url, '', false, ABSPATH, null) ) ) {
1389
+ return array(
1390
+ 'error' => 'Unable to get file system credentials'
1391
+ ); // stop processing here
1392
+ }
1393
+ ob_end_clean();
1394
+
1395
+ if ( ! WP_Filesystem($creds, ABSPATH) ) {
1396
+ //request_filesystem_credentials($url, '', true, false, null);
1397
+ return array(
1398
+ 'error' => 'Unable to initiate file system. Please check you have entered valid FTP credentials.'
1399
+ ); // stop processing here
1400
+ //return;
1401
+ }
1402
+
1403
+ require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php');//will be used to copy from temp directory
1404
+
1405
+ // do process
1406
+ $temp_dir = get_temp_dir();
1407
+ $new_temp_folder = untrailingslashit($temp_dir);
1408
+ $temp_uniq = md5(microtime(1));//should be random
1409
+ while (is_dir($new_temp_folder .'/'. $temp_uniq )) {
1410
+ $temp_uniq = md5(microtime(1));
1411
+ }
1412
+ $new_temp_folder = trailingslashit($new_temp_folder .'/'. $temp_uniq);
1413
+ $is_dir_created = mkdir($new_temp_folder);// new folder should be empty
1414
+ if(!$is_dir_created){
1415
+ return array(
1416
+ 'error' => 'Unable to create a temporary directory.'
1417
+ );
1418
+ }
1419
+
1420
+ //echo '<pre>$new_temp_folder:'; var_dump($new_temp_folder); echo '</pre>';
1421
+
1422
+
1423
+ $remote_abspath = $wp_filesystem->abspath();
1424
+ if(!empty($remote_abspath)){
1425
+ $remote_abspath = trailingslashit($remote_abspath);
1426
+ }else{
1427
+ return array(
1428
+ 'error' => 'Unable to locate WP root directory using file system.'
1429
+ );
1430
+ }
1431
+
1432
+ //global $wp_filesystem;
1433
+ // $wp_filesystem->put_contents(
1434
+ // '/tmp/example.txt',
1435
+ // 'Example contents of a file',
1436
+ // FS_CHMOD_FILE // predefined mode settings for WP files
1437
+ // );
1438
+
1439
+ /////////////////// dev ////////////////////////
1440
+
1441
+ if ($backup_file && file_exists($backup_file)) {
1442
+ if ($overwrite) {//clone only fresh or existing to existing
1443
+ //Keep old db credentials before overwrite
1444
+ if (!$wp_filesystem->copy($remote_abspath . 'wp-config.php', $remote_abspath . 'iwp-temp-wp-config.php', true)) {
1445
+ if($unlink_file) @unlink($backup_file);
1446
+ return array(
1447
+ 'error' => 'Error creating wp-config. Please check your write permissions.'
1448
+ );
1449
+ }
1450
+
1451
+ $db_host = DB_HOST;
1452
+ $db_user = DB_USER;
1453
+ $db_password = DB_PASSWORD;
1454
+ $home = rtrim(get_option('home'), "/");
1455
+ $site_url = get_option('site_url');
1456
+
1457
+ $clone_options = array();
1458
+ if (trim($clone_from_url) || trim($iwp_clone) || trim($maintain_old_key)) {
1459
+
1460
+ $clone_options['iwp_client_nossl_key'] = get_option('iwp_client_nossl_key');
1461
+ $clone_options['iwp_client_public_key'] = get_option('iwp_client_public_key');
1462
+ $clone_options['iwp_client_action_message_id'] = get_option('iwp_client_action_message_id');
1463
+
1464
+ }
1465
+
1466
+ $clone_options['iwp_client_backup_tasks'] = serialize(get_option('iwp_client_backup_tasks'));
1467
+ $clone_options['iwp_client_notifications'] = serialize(get_option('iwp_client_notifications'));
1468
+ $clone_options['iwp_client_pageview_alerts'] = serialize(get_option('iwp_client_pageview_alerts'));
1469
+
1470
+
1471
+ } else {
1472
+ $restore_options = array();
1473
+ $restore_options['iwp_client_notifications'] = serialize(get_option('iwp_client_notifications'));
1474
+ $restore_options['iwp_client_pageview_alerts'] = serialize(get_option('iwp_client_pageview_alerts'));
1475
+ $restore_options['iwp_client_user_hit_count'] = serialize(get_option('iwp_client_user_hit_count'));
1476
+ $restore_options['iwp_client_backup_tasks'] = serialize(get_option('iwp_client_backup_tasks'));
1477
+ }
1478
+
1479
+
1480
+
1481
+
1482
+ //Backup file will be extracted to a temporary path
1483
+
1484
+ //chdir(ABSPATH);
1485
+ $unzip = $this->get_unzip();
1486
+ $command = "$unzip -o $backup_file -d $new_temp_folder";
1487
+ iwp_mmb_print_flush('ZIP Extract CMD: Start');
1488
+ ob_start();
1489
+ $result = $this->iwp_mmb_exec($command);
1490
+ ob_get_clean();
1491
+ iwp_mmb_print_flush('ZIP Extract CMD: End');
1492
+
1493
+ if (!$result) { //fallback to pclzip
1494
+ define('PCLZIP_TEMPORARY_DIR', IWP_BACKUP_DIR . '/');
1495
+ //require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
1496
+ require_once $GLOBALS['iwp_mmb_plugin_dir'].'/pclzip.class.php';
1497
+ iwp_mmb_print_flush('ZIP Extract PCL: Start');
1498
+ $archive = new IWPPclZip($backup_file);
1499
+ $result = $archive->extract(PCLZIP_OPT_PATH, $new_temp_folder, PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
1500
+ iwp_mmb_print_flush('ZIP Extract PCL: End');
1501
+ }
1502
+ $this->wpdb_reconnect();
1503
+
1504
+ if ($unlink_file) {
1505
+ @unlink($backup_file);
1506
+ }
1507
+
1508
+ if (!$result) {
1509
+ return array(
1510
+ 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
1511
+ );
1512
+ }
1513
+
1514
+ $db_result = $this->restore_db($new_temp_folder);
1515
+
1516
+ if (!$db_result) {
1517
+ return array(
1518
+ 'error' => 'Error restoring database.'
1519
+ );
1520
+ } else if(is_array($db_result) && isset($db_result['error'])){
1521
+ return array(
1522
+ 'error' => $db_result['error']
1523
+ );
1524
+ }
1525
+
1526
+ } else {
1527
+ return array(
1528
+ 'error' => 'Backup file not found.'
1529
+ );
1530
+ }
1531
+
1532
+
1533
+ //copy files from temp to ABSPATH
1534
+ $copy_result = $this->iwp_mmb_direct_to_any_copy_dir($new_temp_folder, $remote_abspath);
1535
+
1536
+ if ( is_wp_error($copy_result) ){
1537
+ $wp_temp_direct2 = new WP_Filesystem_Direct('');
1538
+ $wp_temp_direct2->delete($new_temp_folder, true);
1539
+ return $copy_result;
1540
+ }
1541
+
1542
+
1543
+ $this->wpdb_reconnect();
1544
+
1545
+
1546
+
1547
+ //Replace options and content urls
1548
+ if ($overwrite) {//fresh WP package or existing to existing site
1549
+ //Get New Table prefix
1550
+ $new_table_prefix = trim($this->get_table_prefix());
1551
+ //Retrieve old wp_config
1552
+ //@unlink(ABSPATH . 'wp-config.php');
1553
+ $wp_filesystem->delete($remote_abspath . 'wp-config.php', false, 'f');
1554
+ //Replace table prefix
1555
+ //$lines = file(ABSPATH . 'iwp-temp-wp-config.php');
1556
+ $lines = $wp_filesystem->get_contents_array($remote_abspath . 'iwp-temp-wp-config.php');
1557
+
1558
+ $new_lines = '';
1559
+ foreach ($lines as $line) {
1560
+ if (strstr($line, '$table_prefix')) {
1561
+ $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
1562
+ }
1563
+ $new_lines .= $line;
1564
+ //file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
1565
+ }
1566
+
1567
+ $wp_filesystem->put_contents($remote_abspath . 'wp-config.php', $new_lines);
1568
+
1569
+ //@unlink(ABSPATH . 'iwp-temp-wp-config.php');
1570
+ $wp_filesystem->delete($remote_abspath . 'iwp-temp-wp-config.php', false, 'f');
1571
+
1572
+ //Replace options
1573
+ $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
1574
+ $old = $wpdb->get_var($query);
1575
+ $old = rtrim($old, "/");
1576
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'home'";
1577
+ $wpdb->query($wpdb->prepare($query, $home));
1578
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'siteurl'";
1579
+ $wpdb->query($wpdb->prepare($query, $home));
1580
+ //Replace content urls
1581
+
1582
+ $regexp1 = 'src="(.*)'.$old.'(.*)"';
1583
+ $regexp2 = 'href="(.*)'.$old.'(.*)"';
1584
+ $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, %s,%s) WHERE post_content REGEXP %s OR post_content REGEXP %s";
1585
+ $wpdb->query($wpdb->prepare($query, $old, $home, $regexp1, $regexp2));
1586
+
1587
+ if (trim($new_password)) {
1588
+ $new_password = wp_hash_password($new_password);
1589
+ }
1590
+ if (!trim($clone_from_url) && !trim($iwp_clone)) {
1591
+ if ($new_user && $new_password) {
1592
+ $query = "UPDATE " . $new_table_prefix . "users SET user_login = %s, user_pass = %s WHERE user_login = %s";
1593
+ $wpdb->query($wpdb->prepare($query, $new_user, $new_password, $old_user));
1594
+ }
1595
+ } else {
1596
+
1597
+ // if ($iwp_clone) {
1598
+ if ($admin_email) {
1599
+ //Clean Install
1600
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'admin_email'";
1601
+ $wpdb->query($wpdb->prepare($query, $admin_email));
1602
+ $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
1603
+ $temp_user = $wpdb->get_row($query);
1604
+ if (!empty($temp_user)) {
1605
+ $query = "UPDATE " . $new_table_prefix . "users SET user_email=%s, user_login = %s, user_pass = %s WHERE user_login = %s";
1606
+ $wpdb->query($wpdb->prepare($query, $admin_email, $new_user, $new_password, $temp_user->user_login));
1607
+ }
1608
+
1609
+ }
1610
+ // }
1611
+
1612
+ //if ($clone_from_url) {
1613
+ if ($new_user && $new_password) {
1614
+ $query = "UPDATE " . $new_table_prefix . "users SET user_pass = %s WHERE user_login = %s";
1615
+ $wpdb->query($wpdb->prepare($query, $new_password, $new_user));
1616
+ }
1617
+ // }
1618
+
1619
+ }
1620
+
1621
+ if (is_array($clone_options) && !empty($clone_options)) {
1622
+ foreach ($clone_options as $key => $option) {
1623
+ if (!empty($key)) {
1624
+ $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = %s";
1625
+ $res = $wpdb->get_var($wpdb->prepare($query, $key));
1626
+ if ($res == false) {
1627
+ $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES(%s,%s)";
1628
+ $wpdb->query($wpdb->prepare($query, $option, $key));
1629
+ } else {
1630
+ $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = %s";
1631
+ $wpdb->query($wpdb->prepare($query, $option, $key));
1632
+ }
1633
+ }
1634
+ }
1635
+ }
1636
+
1637
+ //Remove hit count
1638
+ $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'iwp_client_user_hit_count'";
1639
+ $wpdb->query($query);
1640
+
1641
+ //Check for .htaccess permalinks update
1642
+ $this->replace_htaccess($home, $remote_abspath);
1643
+ } else {
1644
+ //restore client options
1645
+ if (is_array($restore_options) && !empty($restore_options)) {
1646
+ foreach ($restore_options as $key => $option) {
1647
+ if (!empty($key)) {
1648
+ $query = "SELECT option_value FROM " . $wpdb->base_prefix . "options WHERE option_name = %s";
1649
+ $res = $wpdb->get_var($wpdb->prepare($query, $key));
1650
+ if ($res == false) {
1651
+ $query = "INSERT INTO " . $wpdb->base_prefix . "options (option_value,option_name) VALUES(%s,%s)";
1652
+ $wpdb->query($wpdb->prepare($query, $option, $key));
1653
+ } else {
1654
+ $query = "UPDATE " . $wpdb->base_prefix . "options SET option_value = %s WHERE option_name = %s";
1655
+ $wpdb->query($wpdb->prepare($query, $option, $key));
1656
+ }
1657
+ }
1658
+
1659
+ /*$test = update_option($key,$option);*/
1660
+ }
1661
+ }
1662
+ }
1663
+
1664
+ //clear the temp directory
1665
+ $wp_temp_direct2 = new WP_Filesystem_Direct('');
1666
+ $wp_temp_direct2->delete($new_temp_folder, true);
1667
+
1668
+ return !empty($new_user) ? $new_user : true ;
1669
+ }
1670
+
1671
+ function restore_db($new_temp_folder)
1672
+ {
1673
+ global $wpdb;
1674
+ $paths = $this->check_mysql_paths();
1675
+ $file_path = $new_temp_folder . '/iwp_db';
1676
+ @chmod($file_path,0755);
1677
+ $file_name = glob($file_path . '/*.sql');
1678
+ $file_name = $file_name[0];
1679
+
1680
+ if(!$file_name){
1681
+ return array('error' => 'Cannot access database file.');
1682
+ }
1683
+
1684
+ $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1685
+ $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
1686
+ iwp_mmb_print_flush('DB Restore CMD: Start');
1687
+ ob_start();
1688
+ $result = $this->iwp_mmb_exec($command);
1689
+ ob_get_clean();
1690
+ iwp_mmb_print_flush('DB Restore CMD: End');
1691
+ if (!$result) {
1692
+ //try php
1693
+ $this->restore_db_php($file_name);
1694
+ }
1695
+
1696
+
1697
+ @unlink($file_name);
1698
+ @unlink(dirname($file_name).'/index.php');
1699
+ @rmdir(dirname($file_name));//remove its folder
1700
+ return true;
1701
+ }
1702
+
1703
+ function restore_db_php($file_name)
1704
+ {
1705
+
1706
+ $this->wpdb_reconnect();
1707
+ global $wpdb;
1708
+
1709
+ $wpdb->query("SET NAMES 'utf8'");
1710
+
1711
+ $current_query = '';
1712
+ // Read in entire file
1713
+ $lines = file($file_name);
1714
+ // Loop through each line
1715
+ if(!empty($lines)){
1716
+ foreach ($lines as $line) {
1717
+ iwp_mmb_auto_print('restore_db_php');
1718
+ // Skip it if it's a comment
1719
+ if (substr($line, 0, 2) == '--' || $line == '')
1720
+ continue;
1721
+
1722
+ // Add this line to the current query
1723
+ $current_query .= $line;
1724
+ // If it has a semicolon at the end, it's the end of the query
1725
+ if (substr(trim($line), -1, 1) == ';') {
1726
+ // Perform the query
1727
+ $result = $wpdb->query($current_query);
1728
+ if ($result === false)
1729
+ return false;
1730
+ // Reset temp variable to empty
1731
+ $current_query = '';
1732
+ }
1733
+ }
1734
+ }
1735
+
1736
+ return true;
1737
+ }
1738
+
1739
+ function get_table_prefix()
1740
+ {
1741
+ $lines = file(ABSPATH . 'wp-config.php');
1742
+ foreach ($lines as $line) {
1743
+ if (strstr($line, '$table_prefix')) {
1744
+ $pattern = "/(\'|\")[^(\'|\")]*/";
1745
+ preg_match($pattern, $line, $matches);
1746
+ $prefix = substr($matches[0], 1);
1747
+ return $prefix;
1748
+ break;
1749
+ }
1750
+ }
1751
+ return 'wp_'; //default
1752
+ }
1753
+
1754
+ function optimize_tables()
1755
+ {
1756
+ global $wpdb;
1757
+ $query = 'SHOW TABLE STATUS';
1758
+ $tables = $wpdb->get_results($query, ARRAY_A);
1759
+ foreach ($tables as $table) {
1760
+ if (in_array($table['Engine'], array(
1761
+ 'MyISAM',
1762
+ 'ISAM',
1763
+ 'HEAP',
1764
+ 'MEMORY',
1765
+ 'ARCHIVE'
1766
+ )))
1767
+ $table_string .= $table['Name'] . ",";
1768
+ elseif ($table['Engine'] == 'InnoDB') {
1769
+ $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1770
+ }
1771
+ }
1772
+
1773
+ if(!empty($table_string)){
1774
+ $table_string = rtrim($table_string, ',');
1775
+ $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1776
+ }
1777
+
1778
+ return $optimize ? true : false;
1779
+ }
1780
+
1781
+ ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1782
+ function check_mysql_paths()
1783
+ {
1784
+ global $wpdb;
1785
+ $paths = array(
1786
+ 'mysql' => '',
1787
+ 'mysqldump' => ''
1788
+ );
1789
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
1790
+ $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1791
+ if ($mysql_install) {
1792
+ $install_path = str_replace('\\', '/', $mysql_install->Value);
1793
+ $paths['mysql'] = $install_path . 'bin/mysql.exe';
1794
+ $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1795
+ } else {
1796
+ $paths['mysql'] = 'mysql.exe';
1797
+ $paths['mysqldump'] = 'mysqldump.exe';
1798
+ }
1799
+ } else {
1800
+ $paths['mysql'] = $this->iwp_mmb_exec('which mysql', true);
1801
+ if (empty($paths['mysql']))
1802
+ $paths['mysql'] = 'mysql'; // try anyway
1803
+
1804
+ $paths['mysqldump'] = $this->iwp_mmb_exec('which mysqldump', true);
1805
+ if (empty($paths['mysqldump']))
1806
+ $paths['mysqldump'] = 'mysqldump'; // try anyway
1807
+
1808
+ }
1809
+
1810
+
1811
+ return $paths;
1812
+ }
1813
+
1814
+ //Check if exec, system, passthru functions exist
1815
+ function check_sys()
1816
+ {
1817
+ if ($this->iwp_mmb_function_exists('exec'))
1818
+ return 'exec';
1819
+
1820
+ if ($this->iwp_mmb_function_exists('system'))
1821
+ return 'system';
1822
+
1823
+ if ($this->iwp_mmb_function_exists('passhtru'))
1824
+ return 'passthru';
1825
+
1826
+ return false;
1827
+
1828
+ }
1829
+
1830
+ function iwp_mmb_exec($command, $string = false, $rawreturn = false)
1831
+ {
1832
+ if ($command == '')
1833
+ return false;
1834
+
1835
+ if ($this->iwp_mmb_function_exists('exec')) {
1836
+ $log = @exec($command, $output, $return);
1837
+
1838
+ if ($string)
1839
+ return $log;
1840
+ if ($rawreturn)
1841
+ return $return;
1842
+
1843
+ return $return ? false : true;
1844
+ } elseif ($this->iwp_mmb_function_exists('system')) {
1845
+ $log = @system($command, $return);
1846
+
1847
+ if ($string)
1848
+ return $log;
1849
+
1850
+ if ($rawreturn)
1851
+ return $return;
1852
+
1853
+ return $return ? false : true;
1854
+ } elseif ($this->iwp_mmb_function_exists('passthru') && !$string) {
1855
+ $log = passthru($command, $return);
1856
+
1857
+ if ($rawreturn)
1858
+ return $return;
1859
+
1860
+ return $return ? false : true;
1861
+ }
1862
+
1863
+ if ($rawreturn)
1864
+ return -1;
1865
+
1866
+ return false;
1867
+ }
1868
+
1869
+ function get_zip()
1870
+ {
1871
+ $zip = $this->iwp_mmb_exec('which zip', true);
1872
+ if (!$zip)
1873
+ $zip = "zip";
1874
+ return $zip;
1875
+ }
1876
+
1877
+ function get_unzip()
1878
+ {
1879
+ $unzip = $this->iwp_mmb_exec('which unzip', true);
1880
+ if (!$unzip)
1881
+ $unzip = "unzip";
1882
+ return $unzip;
1883
+ }
1884
+
1885
+ function check_backup_compat()
1886
+ {
1887
+ $reqs = array();
1888
+ if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1889
+ $reqs['Server OS']['status'] = 'Linux (or compatible)';
1890
+ $reqs['Server OS']['pass'] = true;
1891
+ } else {
1892
+ $reqs['Server OS']['status'] = 'Windows';
1893
+ $reqs['Server OS']['pass'] = true;
1894
+ $pass = false;
1895
+ }
1896
+ $reqs['PHP Version']['status'] = phpversion();
1897
+ if ((float) phpversion() >= 5.1) {
1898
+ $reqs['PHP Version']['pass'] = true;
1899
+ } else {
1900
+ $reqs['PHP Version']['pass'] = false;
1901
+ $pass = false;
1902
+ }
1903
+
1904
+
1905
+ if (is_writable(WP_CONTENT_DIR)) {
1906
+ $reqs['Backup Folder']['status'] = "writable";
1907
+ $reqs['Backup Folder']['pass'] = true;
1908
+ } else {
1909
+ $reqs['Backup Folder']['status'] = "not writable";
1910
+ $reqs['Backup Folder']['pass'] = false;
1911
+ }
1912
+
1913
+
1914
+ $file_path = IWP_BACKUP_DIR;
1915
+ $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1916
+
1917
+ if ($func = $this->check_sys()) {
1918
+ $reqs['Execute Function']['status'] = $func;
1919
+ $reqs['Execute Function']['pass'] = true;
1920
+ } else {
1921
+ $reqs['Execute Function']['status'] = "not found";
1922
+ $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1923
+ $reqs['Execute Function']['pass'] = false;
1924
+ }
1925
+ $reqs['Zip']['status'] = $this->get_zip();
1926
+
1927
+ $reqs['Zip']['pass'] = true;
1928
+
1929
+
1930
+
1931
+ $reqs['Unzip']['status'] = $this->get_unzip();
1932
+
1933
+ $reqs['Unzip']['pass'] = true;
1934
+
1935
+ $paths = $this->check_mysql_paths();
1936
+
1937
+ if (!empty($paths['mysqldump'])) {
1938
+ $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1939
+ $reqs['MySQL Dump']['pass'] = true;
1940
+ } else {
1941
+ $reqs['MySQL Dump']['status'] = "not found";
1942
+ $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1943
+ $reqs['MySQL Dump']['pass'] = false;
1944
+ }
1945
+
1946
+ $exec_time = ini_get('max_execution_time');
1947
+ $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1948
+ $reqs['Execution time']['pass'] = true;
1949
+
1950
+ $mem_limit = ini_get('memory_limit');
1951
+ $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1952
+ $reqs['Memory limit']['pass'] = true;
1953
+
1954
+
1955
+ return $reqs;
1956
+ }
1957
+
1958
+ function ftp_backup($args)
1959
+ {
1960
+ extract($args);
1961
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1962
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
1963
+ if ($ftp_ssl) {
1964
+ if (function_exists('ftp_ssl_connect')) {
1965
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1966
+ if ($conn_id === false) {
1967
+ return array(
1968
+ 'error' => 'Failed to connect to ' . $ftp_hostname,
1969
+ 'partial' => 1
1970
+ );
1971
+ }
1972
+ } else {
1973
+ return array(
1974
+ 'error' => 'Your server doesn\'t support FTP SSL',
1975
+ 'partial' => 1
1976
+ );
1977
+ }
1978
+ } else {
1979
+ if (function_exists('ftp_connect')) {
1980
+ $conn_id = ftp_connect($ftp_hostname,$port);
1981
+ if ($conn_id === false) {
1982
+ return array(
1983
+ 'error' => 'Failed to connect to ' . $ftp_hostname,
1984
+ 'partial' => 1
1985
+ );
1986
+ }
1987
+ } else {
1988
+ return array(
1989
+ 'error' => 'Your server doesn\'t support FTP',
1990
+ 'partial' => 1
1991
+ );
1992
+ }
1993
+ }
1994
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1995
+ if ($login === false) {
1996
+ return array(
1997
+ 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1998
+ 'partial' => 1
1999
+ );
2000
+ }
2001
+
2002
+ if($ftp_passive){
2003
+ @ftp_pasv($conn_id,true);
2004
+ }
2005
+
2006
+ @ftp_mkdir($conn_id, $ftp_remote_folder);
2007
+ if ($ftp_site_folder) {
2008
+ $ftp_remote_folder .= '/' . $this->site_name;
2009
+ }
2010
+ @ftp_mkdir($conn_id, $ftp_remote_folder);
2011
+
2012
+ $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
2013
+
2014
+ if ($upload === false) { //Try ascii
2015
+ $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
2016
+ }
2017
+ @ftp_close($conn_id);
2018
+
2019
+ if ($upload === false) {
2020
+ return array(
2021
+ 'error' => 'Failed to upload file to FTP. Please check your specified path.',
2022
+ 'partial' => 1
2023
+ );
2024
+ }
2025
+
2026
+ return true;
2027
+ }
2028
+
2029
+ function remove_ftp_backup($args)
2030
+ {
2031
+ extract($args);
2032
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
2033
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
2034
+ if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
2035
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
2036
+ } else if (function_exists('ftp_connect')) {
2037
+ $conn_id = ftp_connect($ftp_hostname,$port);
2038
+ }
2039
+
2040
+ if ($conn_id) {
2041
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
2042
+ if ($ftp_site_folder)
2043
+ $ftp_remote_folder .= '/' . $this->site_name;
2044
+
2045
+ if($ftp_passive){
2046
+ @ftp_pasv($conn_id,true);
2047
+ }
2048
+
2049
+ $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
2050
+
2051
+ ftp_close($conn_id);
2052
+ }
2053
+
2054
+ }
2055
+
2056
+ function get_ftp_backup($args)
2057
+ {
2058
+ extract($args);
2059
+ //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
2060
+ $port = $ftp_port ? $ftp_port : 21; //default port is 21
2061
+ if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
2062
+ $conn_id = ftp_ssl_connect($ftp_hostname,$port);
2063
+
2064
+ } else if (function_exists('ftp_connect')) {
2065
+ $conn_id = ftp_connect($ftp_hostname,$port);
2066
+ if ($conn_id === false) {
2067
+ return false;
2068
+ }
2069
+ }
2070
+ $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
2071
+ if ($login === false) {
2072
+ return false;
2073
+ }
2074
+
2075
+ if ($ftp_site_folder)
2076
+ $ftp_remote_folder .= '/' . $this->site_name;
2077
+
2078
+ if($ftp_passive){
2079
+ @ftp_pasv($conn_id,true);
2080
+ }
2081
+
2082
+ //$temp = ABSPATH . 'iwp_temp_backup.zip';
2083
+ $temp = wp_tempnam('iwp_temp_backup.zip');
2084
+
2085
+ $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
2086
+ if ($get === false) {
2087
+ return false;
2088
+ } else {
2089
+ }
2090
+ ftp_close($conn_id);
2091
+
2092
+ return $temp;
2093
+ }
2094
+
2095
+
2096
+ function dropbox_backup($args){
2097
+ extract($args);
2098
+
2099
+ if(isset($consumer_secret) && !empty($consumer_secret)){
2100
+
2101
+ require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2102
+
2103
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
2104
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2105
+
2106
+ if ($dropbox_site_folder == true)
2107
+ $dropbox_destination .= '/' . $this->site_name . '/' . basename($backup_file);
2108
+ else
2109
+ $dropbox_destination .= '/' . basename($backup_file);
2110
+
2111
+ try {
2112
+ $dropbox->upload($backup_file, $dropbox_destination, true);
2113
+ } catch (Exception $e) {
2114
+ $this->_log($e->getMessage());
2115
+ return array(
2116
+ 'error' => $e->getMessage(),
2117
+ 'partial' => 1
2118
+ );
2119
+ }
2120
+
2121
+ return true;
2122
+
2123
+ } else {
2124
+ return array(
2125
+ 'error' => 'Please connect your InfiniteWP panel with your Dropbox account.'
2126
+ );
2127
+ }
2128
+
2129
+ }
2130
+
2131
+
2132
+ function remove_dropbox_backup($args) {
2133
+ extract($args);
2134
+
2135
+ require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2136
+
2137
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
2138
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2139
+
2140
+ if ($dropbox_site_folder == true)
2141
+ $dropbox_destination .= '/' . $this->site_name;
2142
+
2143
+ try {
2144
+ $dropbox->fileopsDelete($dropbox_destination . '/' . $backup_file);
2145
+ } catch (Exception $e) {
2146
+ $this->_log($e->getMessage());
2147
+ /*return array(
2148
+ 'error' => $e->getMessage(),
2149
+ 'partial' => 1
2150
+ );*/
2151
+ }
2152
+
2153
+ //return true;
2154
+ }
2155
+
2156
+
2157
+ function get_dropbox_backup($args) {
2158
+ extract($args);
2159
+
2160
+ require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/dropbox.php';
2161
+
2162
+ $dropbox = new Dropbox($consumer_key, $consumer_secret);
2163
+ $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2164
+
2165
+ if ($dropbox_site_folder == true)
2166
+ $dropbox_destination .= '/' . $this->site_name;
2167
+
2168
+ //$temp = ABSPATH . 'iwp_temp_backup.zip';
2169
+ $temp = wp_tempnam('iwp_temp_backup.zip');
2170
+
2171
+ try {
2172
+
2173
+ $file = $dropbox->download($dropbox_destination.'/'.$backup_file);
2174
+ $handle = @fopen($temp, 'w');
2175
+ $result = fwrite($handle, $file);
2176
+ fclose($handle);
2177
+
2178
+ if($result)
2179
+ return $temp;
2180
+ else
2181
+ return false;
2182
+ } catch (Exception $e) {
2183
+ $this->_log($e->getMessage());
2184
+ return array(
2185
+ 'error' => $e->getMessage(),
2186
+ 'partial' => 1
2187
+ );
2188
+ }
2189
+ }
2190
+
2191
+
2192
+ function amazons3_backup($args)
2193
+ {
2194
+ if ($this->iwp_mmb_function_exists('curl_init')) {
2195
+ require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2196
+
2197
+ extract($args);
2198
+
2199
+ if ($as3_site_folder == true)
2200
+ $as3_directory .= '/' . $this->site_name;
2201
+
2202
+ try{
2203
+
2204
+ CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true, 'use_ssl'=>false, 'ssl_verification'=>false), '@default' => 'development'));
2205
+ $s3 = new AmazonS3();
2206
+ $response = $s3->create_object($as3_bucket, $as3_directory . '/' . basename($backup_file), array('fileUpload' => $backup_file));
2207
+ $upload = $response->isOk();
2208
+ if($upload) {
2209
+ return true;
2210
+ } else {
2211
+ return array(
2212
+ 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
2213
+ 'partial' => 1
2214
+ );
2215
+ }
2216
+
2217
+ }catch (Exception $e){
2218
+ $err = $e->getMessage();
2219
+ if($err){
2220
+ return array(
2221
+ 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
2222
+ );
2223
+ } else {
2224
+ return array(
2225
+ 'error' => 'Failed to upload to Amazon S3.'
2226
+ );
2227
+ }
2228
+ }
2229
+ } else {
2230
+ return array(
2231
+ 'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
2232
+ 'partial' => 1
2233
+ );
2234
+ }
2235
+ }
2236
+
2237
+
2238
+ function remove_amazons3_backup($args)
2239
+ {
2240
+ if ($this->iwp_mmb_function_exists('curl_init')) {
2241
+ require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2242
+ extract($args);
2243
+ if ($as3_site_folder == true)
2244
+ $as3_directory .= '/' . $this->site_name;
2245
+ try{
2246
+ CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true), '@default' => 'development'));
2247
+ $s3 = new AmazonS3();
2248
+ $s3->delete_object($as3_bucket, $as3_directory . '/' . $backup_file);
2249
+ } catch (Exception $e){
2250
+
2251
+ }
2252
+ }
2253
+ }
2254
+
2255
+ function get_amazons3_backup($args)
2256
+ {
2257
+ require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/amazon_s3/sdk.class.php');
2258
+ extract($args);
2259
+ $temp = '';
2260
+ try{
2261
+ CFCredentials::set(array('development' => array('key' => trim($as3_access_key), 'secret' => trim(str_replace(' ', '+', $as3_secure_key)), 'default_cache_config' => '', 'certificate_authority' => true), '@default' => 'development'));
2262
+ $s3 = new AmazonS3();
2263
+ if ($as3_site_folder == true)
2264
+ $as3_directory .= '/' . $this->site_name;
2265
+
2266
+ //$temp = ABSPATH . 'iwp_temp_backup.zip';
2267
+ $temp = wp_tempnam('iwp_temp_backup.zip');
2268
+ $s3->get_object($as3_bucket, $as3_directory . '/' . $backup_file, array("fileDownload" => $temp));
2269
+ } catch (Exception $e){
2270
+ return $temp;
2271
+ }
2272
+ return $temp;
2273
+ }
2274
+ //IWP Remove ends here
2275
+
2276
+
2277
+ function schedule_next($type, $schedule)
2278
+ {
2279
+ $schedule = explode("|", $schedule);
2280
+ if (empty($schedule))
2281
+ return false;
2282
+ switch ($type) {
2283
+
2284
+ case 'daily':
2285
+
2286
+ if (isset($schedule[1]) && $schedule[1]) {
2287
+ $delay_time = $schedule[1] * 60;
2288
+ }
2289
+
2290
+ $current_hour = date("H");
2291
+ $schedule_hour = $schedule[0];
2292
+ if ($current_hour >= $schedule_hour){
2293
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
2294
+ //$time ='0001#'.$current_hour.'|'.$schedule_hour;
2295
+
2296
+ }
2297
+
2298
+ else{
2299
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2300
+ //$time ='0000#'.$current_hour.'|'.$schedule_hour;
2301
+ }
2302
+ $time = time() + 30;
2303
+
2304
+
2305
+ break;
2306
+
2307
+
2308
+ case 'weekly':
2309
+ if (isset($schedule[2]) && $schedule[2]) {
2310
+ $delay_time = $schedule[2] * 60;
2311
+ }
2312
+ $current_weekday = date('w');
2313
+ $schedule_weekday = $schedule[1];
2314
+ $current_hour = date("H");
2315
+ $schedule_hour = $schedule[0];
2316
+
2317
+ if ($current_weekday > $schedule_weekday)
2318
+ $weekday_offset = 7 - ($week_day - $task_schedule[1]);
2319
+ else
2320
+ $weekday_offset = $schedule_weekday - $current_weekday;
2321
+
2322
+
2323
+ if (!$weekday_offset) { //today is scheduled weekday
2324
+ if ($current_hour >= $schedule_hour)
2325
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
2326
+ else
2327
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2328
+ } else {
2329
+ $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
2330
+ }
2331
+
2332
+ break;
2333
+
2334
+ case 'monthly':
2335
+ if (isset($schedule[2]) && $schedule[2]) {
2336
+ $delay_time = $schedule[2] * 60;
2337
+ }
2338
+ $current_monthday = date('j');
2339
+ $schedule_monthday = $schedule[1];
2340
+ $current_hour = date("H");
2341
+ $schedule_hour = $schedule[0];
2342
+
2343
+ if ($current_monthday > $schedule_monthday) {
2344
+ $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2345
+ } else if ($current_monthday < $schedule_monthday) {
2346
+ $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2347
+ } else if ($current_monthday == $schedule_monthday) {
2348
+ if ($current_hour >= $schedule_hour)
2349
+ $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2350
+ else
2351
+ $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2352
+ break;
2353
+ }
2354
+
2355
+ break;
2356
+ default:
2357
+ break;
2358
+ }
2359
+
2360
+ if (isset($delay_time) && $delay_time) {
2361
+ $time += $delay_time;
2362
+ }
2363
+
2364
+ return $time;
2365
+ }
2366
+
2367
+
2368
+ //Parse task arguments for info on IWP Admin Panel
2369
+ function get_backup_stats()
2370
+ {
2371
+ $stats = array();
2372
+ $tasks = $this->tasks;
2373
+ if (is_array($tasks) && !empty($tasks)) {
2374
+ foreach ($tasks as $task_name => $info) {
2375
+ if (is_array($info['task_results']) && !empty($info['task_results'])) {
2376
+ foreach ($info['task_results'] as $key => $result) {
2377
+ if (isset($result['server']) && !isset($result['error'])) {
2378
+ if (!file_exists($result['server']['file_path'])) {
2379
+ $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
2380
+ }
2381
+ }
2382
+ }
2383
+ }
2384
+ if (is_array($info['task_results']))
2385
+ $stats[$task_name] = $info['task_results'];
2386
+ }
2387
+ }
2388
+ return $stats;
2389
+ }
2390
+
2391
+
2392
+ function get_next_schedules()
2393
+ {
2394
+ $stats = array();
2395
+ $tasks = $this->tasks;
2396
+ if (is_array($tasks) && !empty($tasks)) {
2397
+ foreach ($tasks as $task_name => $info) {
2398
+ $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
2399
+ }
2400
+ }
2401
+ return $stats;
2402
+ }
2403
+
2404
+
2405
+ function remove_old_backups($task_name)
2406
+ {
2407
+ //Check for previous failed backups first
2408
+ $this->cleanup();
2409
+
2410
+ //Remove by limit
2411
+ $backups = $this->tasks;
2412
+ if ($task_name == 'Backup Now') {
2413
+ $num = 0;
2414
+ } else {
2415
+ $num = 1;
2416
+ }
2417
+
2418
+
2419
+ if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
2420
+ //how many to remove ?
2421
+ $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
2422
+ for ($i = 0; $i < $remove_num; $i++) {
2423
+ //Remove from the server
2424
+ if (isset($backups[$task_name]['task_results'][$i]['server'])) {
2425
+ @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
2426
+ }
2427
+
2428
+ if (isset($backups[$task_name]['task_results'][$i]['ftp'])) {
2429
+ $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
2430
+ $args = $backups[$task_name]['task_args']['account_info']['iwp_ftp'];
2431
+ $args['backup_file'] = $ftp_file;
2432
+ $this->remove_ftp_backup($args);
2433
+ }
2434
+
2435
+ if (isset($backups[$task_name]['task_results'][$i]['amazons3'])) {
2436
+ $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
2437
+ $args = $backups[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
2438
+ $args['backup_file'] = $amazons3_file;
2439
+ $this->remove_amazons3_backup($args);
2440
+ }
2441
+
2442
+ if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['iwp_dropbox'])) {
2443
+ //To do: dropbox remove
2444
+ $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
2445
+ $args = $backups[$task_name]['task_args']['account_info']['iwp_dropbox'];
2446
+ $args['backup_file'] = $dropbox_file;
2447
+ $this->remove_dropbox_backup($args);
2448
+ }
2449
+ //Remove database backup info
2450
+ unset($backups[$task_name]['task_results'][$i]);
2451
+
2452
+ } //end foreach
2453
+
2454
+ if (is_array($backups[$task_name]['task_results']))
2455
+ $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
2456
+ else
2457
+ $backups[$task_name]['task_results']=array();
2458
+
2459
+ $this->update_tasks($backups);
2460
+
2461
+ return true;
2462
+ }
2463
+ }
2464
+
2465
+ /**
2466
+ * Delete specified backup
2467
+ * Args: $task_name, $result_id
2468
+ */
2469
+
2470
+ function delete_backup($args)
2471
+ {
2472
+ if (empty($args))
2473
+ return false;
2474
+ extract($args);
2475
+
2476
+ $tasks = $this->tasks;
2477
+ $task = $tasks[$task_name];
2478
+ $backups = $task['task_results'];
2479
+ $backup = $backups[$result_id];
2480
+
2481
+ if (isset($backup['server'])) {
2482
+ @unlink($backup['server']['file_path']);
2483
+ }
2484
+
2485
+ /*
2486
+ //IWP Remove starts here//IWP Remove ends here
2487
+ */
2488
+ //Remove from ftp
2489
+ if (isset($backup['ftp'])) {
2490
+ $ftp_file = $backup['ftp'];
2491
+ $args = $tasks[$task_name]['task_args']['account_info']['iwp_ftp'];
2492
+ $args['backup_file'] = $ftp_file;
2493
+ $this->remove_ftp_backup($args);
2494
+ }
2495
+
2496
+ if (isset($backup['amazons3'])) {
2497
+ $amazons3_file = $backup['amazons3'];
2498
+ $args = $tasks[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
2499
+ $args['backup_file'] = $amazons3_file;
2500
+ $this->remove_amazons3_backup($args);
2501
+ }
2502
+
2503
+ if (isset($backup['dropbox'])) {
2504
+ $dropbox_file = $backup['dropbox'];
2505
+ $args = $tasks[$task_name]['task_args']['account_info']['iwp_dropbox'];
2506
+ $args['backup_file'] = $dropbox_file;
2507
+ $this->remove_dropbox_backup($args);
2508
+ }
2509
+
2510
+
2511
+ unset($backups[$result_id]);
2512
+
2513
+ if (count($backups)) {
2514
+ $tasks[$task_name]['task_results'] = $backups;
2515
+ } else {
2516
+ unset($tasks[$task_name]['task_results']);
2517
+ }
2518
+
2519
+ $this->update_tasks($tasks);
2520
+ //update_option('iwp_client_backup_tasks', $tasks);
2521
+ return true;
2522
+
2523
+ }
2524
+
2525
+ function cleanup()
2526
+ {
2527
+ $tasks = $this->tasks;
2528
+ $backup_folder = WP_CONTENT_DIR . '/' . md5('iwp_mmb-client') . '/iwp_backups/';
2529
+ $backup_folder_new = IWP_BACKUP_DIR . '/';
2530
+ $files = glob($backup_folder . "*");
2531
+ $new = glob($backup_folder_new . "*");
2532
+
2533
+ //Failed db files first
2534
+ $db_folder = IWP_DB_DIR . '/';
2535
+ $db_files = glob($db_folder . "*");
2536
+ if (is_array($db_files) && !empty($db_files)) {
2537
+ foreach ($db_files as $file) {
2538
+ @unlink($file);
2539
+ }
2540
+ @unlink(IWP_BACKUP_DIR.'/iwp_db/index.php');
2541
+ @rmdir(IWP_DB_DIR);
2542
+ }
2543
+
2544
+
2545
+ //clean_old folder?
2546
+ if ((basename($files[0]) == 'index.php' && count($files) == 1) || (!empty($files))) { //USE (!empty($files)
2547
+ foreach ($files as $file) {
2548
+ @unlink($file);
2549
+ }
2550
+ @rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client') . '/iwp_backups');
2551
+ @rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client'));
2552
+ }
2553
+
2554
+ if (!empty($new)) {
2555
+ foreach ($new as $b) {
2556
+ $files[] = $b;
2557
+ }
2558
+ }
2559
+ $deleted = array();
2560
+
2561
+ if (is_array($files) && count($files)) {
2562
+ $results = array();
2563
+ if (!empty($tasks)) {
2564
+ foreach ((array) $tasks as $task) {
2565
+ if (isset($task['task_results']) && count($task['task_results'])) {
2566
+ foreach ($task['task_results'] as $backup) {
2567
+ if (isset($backup['server'])) {
2568
+ $results[] = $backup['server']['file_path'];
2569
+ }
2570
+ }
2571
+ }
2572
+ }
2573
+ }
2574
+
2575
+ $num_deleted = 0;
2576
+ foreach ($files as $file) {
2577
+ if (!in_array($file, $results) && basename($file) != 'index.php') {
2578
+ @unlink($file);
2579
+ $deleted[] = basename($file);
2580
+ $num_deleted++;
2581
+ }
2582
+ }
2583
+ }
2584
+
2585
+
2586
+
2587
+ return $deleted;
2588
+ }
2589
+
2590
+
2591
+ /*
2592
+ */
2593
+
2594
+ function validate_task($args, $url)
2595
+ {
2596
+ if (!class_exists('WP_Http')) {
2597
+ include_once(ABSPATH . WPINC . '/class-http.php');
2598
+ }
2599
+ $params = array();
2600
+ $params['body'] = $args;
2601
+ $result = wp_remote_post($url, $params);
2602
+ if (is_array($result) && $result['body'] == 'iwp_delete_task') {
2603
+ //$tasks = $this->get_backup_settings();
2604
+ $tasks = $this->tasks;
2605
+ unset($tasks[$args['task_name']]);
2606
+ $this->update_tasks($tasks);
2607
+ $this->cleanup();
2608
+ exit;
2609
+ } elseif(is_array($result) && $result['body'] == 'iwp_pause_task'){
2610
+ return 'paused';
2611
+ }
2612
+
2613
+ return 'ok';
2614
+ }
2615
+
2616
+ function update_status($task_name, $status, $completed = false)
2617
+ {
2618
+ /* Statuses:
2619
+ 0 - Backup started
2620
+ 1 - DB dump
2621
+ 2 - DB ZIP
2622
+ 3 - Files ZIP
2623
+ 4 - Amazon S3
2624
+ 5 - Dropbox
2625
+ 6 - FTP
2626
+ 7 - Email
2627
+ 100 - Finished
2628
+ */
2629
+ //if ($task_name != 'Backup Now') {
2630
+ $tasks = $this->tasks;
2631
+ $index = count($tasks[$task_name]['task_results']) - 1;
2632
+ //!is_array($tasks[$task_name]['task_results'][$index]['status']) &&
2633
+ if (!is_array($tasks[$task_name]['task_results'][$index]['backhack_status'])) {
2634
+ //$tasks[$task_name]['task_results'][$index]['status'] = array();
2635
+ $tasks[$task_name]['task_results'][$index]['backhack_status'] = array();
2636
+ }
2637
+ $tasks[$task_name]['task_results'][$index]['backhack_status']['adminHistoryID'] = $GLOBALS['IWP_CLIENT_HISTORY_ID'];
2638
+ if (!$completed) {
2639
+ //$tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
2640
+ $tasks[$task_name]['task_results'][$index]['backhack_status'][$status]['start'] = microtime(true);
2641
+ } else {
2642
+ $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
2643
+ //$tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
2644
+ $tasks[$task_name]['task_results'][$index]['backhack_status'][$status]['end'] = microtime(true);
2645
+ }
2646
+
2647
+ $this->update_tasks($tasks);
2648
+ //update_option('iwp_client_backup_tasks',$tasks);
2649
+ //}
2650
+ }
2651
+
2652
+ function update_tasks($tasks)
2653
+ {
2654
+ $this->tasks = $tasks;
2655
+ update_option('iwp_client_backup_tasks', $tasks);
2656
+ }
2657
+
2658
+ function wpdb_reconnect(){
2659
+ global $wpdb;
2660
+ $old_wpdb = $wpdb;
2661
+ //Reconnect to avoid timeout problem after ZIP files
2662
+ if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
2663
+ @mysql_close($wpdb->dbh);
2664
+ $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
2665
+ wp_set_wpdb_vars();
2666
+ $wpdb->options = $old_wpdb->options;//fix for multi site full backup
2667
+ }
2668
+ }
2669
+
2670
+ function replace_htaccess($url, $remote_abspath)
2671
+ {
2672
+ global $wp_filesystem;
2673
+ //$file = @file_get_contents(ABSPATH.'.htaccess');
2674
+ $file = $wp_filesystem->get_contents($remote_abspath.'.htaccess');
2675
+ if ($file && strlen($file)) {
2676
+ $args = parse_url($url);
2677
+ $string = rtrim($args['path'], "/");
2678
+ $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
2679
+ $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
2680
+ $file = preg_replace($regex, $replace, $file);
2681
+ //@file_put_contents(ABSPATH.'.htaccess', $file);
2682
+ $wp_filesystem->put_contents($remote_abspath.'.htaccess', $file);
2683
+ }
2684
+ }
2685
+
2686
+ function check_cron_remove(){
2687
+ if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
2688
+ wp_clear_scheduled_hook('iwp_client_backup_tasks');
2689
+ exit;
2690
+ }
2691
+ }
2692
+
2693
+
2694
+ public function readd_tasks( $params = array() ){
2695
+ global $iwp_mmb_core;
2696
+
2697
+ if( empty($params) || !isset($params['backups']) )
2698
+ return $params;
2699
+
2700
+ $before = array();
2701
+ $tasks = $params['backups'];
2702
+ if( !empty($tasks) ){
2703
+ $iwp_mmb_backup = new IWP_MMB_Backup();
2704
+
2705
+ if( function_exists( 'wp_next_scheduled' ) ){
2706
+ if ( !wp_next_scheduled('iwp_client_backup_tasks') ) {
2707
+ wp_schedule_event( time(), 'tenminutes', 'iwp_client_backup_tasks' );
2708
+ }
2709
+ }
2710
+
2711
+ foreach( $tasks as $task ){
2712
+ $before[$task['task_name']] = array();
2713
+
2714
+ if(isset($task['secure'])){
2715
+ if($decrypted = $iwp_mmb_core->_secure_data($task['secure'])){
2716
+ $decrypted = maybe_unserialize($decrypted);
2717
+ if(is_array($decrypted)){
2718
+ foreach($decrypted as $key => $val){
2719
+ if(!is_numeric($key))
2720
+ $task[$key] = $val;
2721
+ }
2722
+ unset($task['secure']);
2723
+ } else
2724
+ $task['secure'] = $decrypted;
2725
+ }
2726
+
2727
+ }
2728
+ if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from panel first time(secure data)
2729
+ $task['args']['account_info'] = $task['account_info'];
2730
+ }
2731
+
2732
+ $before[$task['task_name']]['task_args'] = $task['args'];
2733
+ $before[$task['task_name']]['task_args']['next'] = $iwp_mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
2734
+ }
2735
+ }
2736
+ update_option('iwp_client_backup_tasks', $before);
2737
+
2738
+ unset($params['backups']);
2739
+ return $params;
2740
+ }
2741
+
2742
+ function is_server_writable(){
2743
+ if((!defined('FTP_HOST') || !defined('FTP_USER') || !defined('FTP_PASS')) && (get_filesystem_method(array(), ABSPATH) != 'direct'))
2744
+ return false;
2745
+ else
2746
+ return true;
2747
+ }
2748
+ }
2749
+
2750
+ /*if( function_exists('add_filter') ){
2751
+ add_filter( 'iwp_website_add', 'IWP_MMB_Backup::readd_tasks' );
2752
+ }*/
2753
+
2754
+ if(!function_exists('get_all_files_from_dir')) {
2755
+ /**
2756
+ * Get all files in directory
2757
+ *
2758
+ * @param string $path Relative or absolute path to folder
2759
+ * @param array $exclude List of excluded files or folders, relative to $path
2760
+ * @return array List of all files in folder $path, exclude all files in $exclude array
2761
+ */
2762
+ function get_all_files_from_dir($path, $exclude = array()) {
2763
+ if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
2764
+ global $directory_tree, $ignore_array;
2765
+ $directory_tree = array();
2766
+ foreach ($exclude as $file) {
2767
+ if (!in_array($file, array('.', '..'))) {
2768
+ if ($file[0] === "/") $path = substr($file, 1);
2769
+ $ignore_array[] = "$path/$file";
2770
+ }
2771
+ }
2772
+ get_all_files_from_dir_recursive($path);
2773
+ return $directory_tree;
2774
+ }
2775
+ }
2776
+
2777
+ if (!function_exists('get_all_files_from_dir_recursive')) {
2778
+ /**
2779
+ * Get all files in directory,
2780
+ * wrapped function which writes in global variable
2781
+ * and exclued files or folders are read from global variable
2782
+ *
2783
+ * @param string $path Relative or absolute path to folder
2784
+ * @return void
2785
+ */
2786
+ function get_all_files_from_dir_recursive($path) {
2787
+ if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
2788
+ global $directory_tree, $ignore_array;
2789
+ $directory_tree_temp = array();
2790
+ $dh = @opendir($path);
2791
+
2792
+ while (false !== ($file = @readdir($dh))) {
2793
+ if (!in_array($file, array('.', '..'))) {
2794
+ if (!in_array("$path/$file", $ignore_array)) {
2795
+ if (!is_dir("$path/$file")) {
2796
+ $directory_tree[] = "$path/$file";
2797
+ } else {
2798
+ get_all_files_from_dir_recursive("$path/$file");
2799
+ }
2800
+ }
2801
+ }
2802
+ }
2803
+ @closedir($dh);
2804
+ }
2805
+ }
2806
+
2807
  ?>
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: InfiniteWP - Client
4
  Plugin URI: http://infinitewp.com/
5
  Description: This is the client plugin of InfiniteWP that communicates with the InfiniteWP Admin panel.
6
  Author: Revmakx
7
- Version: 1.2.5
8
  Author URI: http://www.revmakx.com
9
  */
10
  /************************************************************
@@ -26,7 +26,7 @@ Author URI: http://www.revmakx.com
26
  **************************************************************/
27
 
28
  if(!defined('IWP_MMB_CLIENT_VERSION'))
29
- define('IWP_MMB_CLIENT_VERSION', '1.2.5');
30
 
31
 
32
  if ( !defined('IWP_MMB_XFRAME_COOKIE')){
4
  Plugin URI: http://infinitewp.com/
5
  Description: This is the client plugin of InfiniteWP that communicates with the InfiniteWP Admin panel.
6
  Author: Revmakx
7
+ Version: 1.2.6
8
  Author URI: http://www.revmakx.com
9
  */
10
  /************************************************************
26
  **************************************************************/
27
 
28
  if(!defined('IWP_MMB_CLIENT_VERSION'))
29
+ define('IWP_MMB_CLIENT_VERSION', '1.2.6');
30
 
31
 
32
  if ( !defined('IWP_MMB_XFRAME_COOKIE')){
lib/amazon_s3/sdk.class.php CHANGED
@@ -1,1556 +1,1556 @@
1
- <?php
2
- /*
3
- * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License").
6
- * You may not use this file except in compliance with the License.
7
- * A copy of the License is located at
8
- *
9
- * http://aws.amazon.com/apache2.0
10
- *
11
- * or in the "license" file accompanying this file. This file is distributed
12
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13
- * express or implied. See the License for the specific language governing
14
- * permissions and limitations under the License.
15
- */
16
-
17
-
18
- /*%******************************************************************************************%*/
19
- // EXCEPTIONS
20
-
21
- /**
22
- * Default CFRuntime Exception.
23
- */
24
- class CFRuntime_Exception extends Exception {}
25
-
26
- /**
27
- * Parsing Exception.
28
- */
29
- class Parser_Exception extends Exception {}
30
-
31
-
32
- /*%******************************************************************************************%*/
33
- // DETERMINE WHAT ENVIRONMENT DATA TO ADD TO THE USERAGENT FOR METRIC TRACKING
34
-
35
- /*
36
- Define a temporary callback function for this calculation. Get the PHP version and any
37
- required/optional extensions that are leveraged.
38
-
39
- Tracking this data gives Amazon better metrics about what configurations are being used
40
- so that forward-looking plans for the code can be made with more certainty (e.g. What
41
- version of PHP are most people running? Do they tend to have the latest PCRE?).
42
- */
43
- function __aws_sdk_ua_callback()
44
- {
45
- $ua_append = '';
46
- $extensions = get_loaded_extensions();
47
- $sorted_extensions = array();
48
-
49
- if ($extensions)
50
- {
51
- foreach ($extensions as $extension)
52
- {
53
- if ($extension === 'curl' && function_exists('curl_version'))
54
- {
55
- $curl_version = curl_version();
56
- $sorted_extensions[strtolower($extension)] = $curl_version['version'];
57
- }
58
- elseif ($extension === 'pcre' && defined('PCRE_VERSION'))
59
- {
60
- $pcre_version = explode(' ', PCRE_VERSION);
61
- $sorted_extensions[strtolower($extension)] = $pcre_version[0];
62
- }
63
- elseif ($extension === 'openssl' && defined('OPENSSL_VERSION_TEXT'))
64
- {
65
- $openssl_version = explode(' ', OPENSSL_VERSION_TEXT);
66
- $sorted_extensions[strtolower($extension)] = $openssl_version[1];
67
- }
68
- else
69
- {
70
- $sorted_extensions[strtolower($extension)] = phpversion($extension);
71
- }
72
- }
73
- }
74
-
75
- foreach (array('simplexml', 'json', 'pcre', 'spl', 'curl', 'openssl', 'apc', 'xcache', 'memcache', 'memcached', 'pdo', 'pdo_sqlite', 'sqlite', 'sqlite3', 'zlib', 'xdebug') as $ua_ext)
76
- {
77
- if (isset($sorted_extensions[$ua_ext]) && $sorted_extensions[$ua_ext])
78
- {
79
- $ua_append .= ' ' . $ua_ext . '/' . $sorted_extensions[$ua_ext];
80
- }
81
- elseif (isset($sorted_extensions[$ua_ext]))
82
- {
83
- $ua_append .= ' ' . $ua_ext . '/0';
84
- }
85
- }
86
-
87
- foreach (array('memory_limit', 'date.timezone', 'open_basedir', 'safe_mode', 'zend.enable_gc') as $cfg)
88
- {
89
- $cfg_value = ini_get($cfg);
90
-
91
- if (in_array($cfg, array('memory_limit', 'date.timezone'), true))
92
- {
93
- $ua_append .= ' ' . $cfg . '/' . str_replace('/', '.', $cfg_value);
94
- }
95
- elseif (in_array($cfg, array('open_basedir', 'safe_mode', 'zend.enable_gc'), true))
96
- {
97
- if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
98
- {
99
- $cfg_value = 'off';
100
- }
101
- elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
102
- {
103
- $cfg_value = 'on';
104
- }
105
-
106
- $ua_append .= ' ' . $cfg . '/' . $cfg_value;
107
- }
108
- }
109
-
110
- return $ua_append;
111
- }
112
-
113
-
114
- /*%******************************************************************************************%*/
115
- // INTERMEDIARY CONSTANTS
116
-
117
- define('CFRUNTIME_NAME', 'aws-sdk-php');
118
- define('CFRUNTIME_VERSION', '1.5.14');
119
- define('CFRUNTIME_BUILD', '20120831150000');
120
- define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . str_replace(' ', '_', php_uname('s')) . '/' . str_replace(' ', '_', php_uname('r')) . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
121
-
122
-
123
- /*%******************************************************************************************%*/
124
- // CLASS
125
-
126
- /**
127
- * Core functionality and default settings shared across all SDK classes. All methods and properties in this
128
- * class are inherited by the service-specific classes.
129
- *
130
- * @version 2012.05.25
131
- * @license See the included NOTICE.md file for more information.
132
- * @copyright See the included NOTICE.md file for more information.
133
- * @link http://aws.amazon.com/php/ PHP Developer Center
134
- */
135
- class CFRuntime
136
- {
137
- /*%******************************************************************************************%*/
138
- // CONSTANTS
139
-
140
- /**
141
- * Name of the software.
142
- */
143
- const NAME = CFRUNTIME_NAME;
144
-
145
- /**
146
- * Version of the software.
147
- */
148
- const VERSION = CFRUNTIME_VERSION;
149
-
150
- /**
151
- * Build ID of the software.
152
- */
153
- const BUILD = CFRUNTIME_BUILD;
154
-
155
- /**
156
- * User agent string used to identify the software.
157
- */
158
- const USERAGENT = CFRUNTIME_USERAGENT;
159
-
160
-
161
- /*%******************************************************************************************%*/
162
- // PROPERTIES
163
-
164
- /**
165
- * The Amazon API Key.
166
- */
167
- public $key;
168
-
169
- /**
170
- * The Amazon API Secret Key.
171
- */
172
- public $secret_key;
173
-
174
- /**
175
- * The Amazon Authentication Token.
176
- */
177
- public $auth_token;
178
-
179
- /**
180
- * Handle for the utility functions.
181
- */
182
- public $util;
183
-
184
- /**
185
- * An identifier for the current AWS service.
186
- */
187
- public $service = null;
188
-
189
- /**
190
- * The supported API version.
191
- */
192
- public $api_version = null;
193
-
194
- /**
195
- * The state of whether auth should be handled as AWS Query.
196
- */
197
- public $use_aws_query = true;
198
-
199
- /**
200
- * The default class to use for utilities (defaults to <CFUtilities>).
201
- */
202
- public $utilities_class = 'CFUtilities';
203
-
204
- /**
205
- * The default class to use for HTTP requests (defaults to <CFRequest>).
206
- */
207
- public $request_class = 'CFRequest';
208
-
209
- /**
210
- * The default class to use for HTTP responses (defaults to <CFResponse>).
211
- */
212
- public $response_class = 'CFResponse';
213
-
214
- /**
215
- * The default class to use for parsing XML (defaults to <CFSimpleXML>).
216
- */
217
- public $parser_class = 'CFSimpleXML';
218
-
219
- /**
220
- * The default class to use for handling batch requests (defaults to <CFBatchRequest>).
221
- */
222
- public $batch_class = 'CFBatchRequest';
223
-
224
- /**
225
- * The state of SSL/HTTPS use.
226
- */
227
- public $use_ssl = true;
228
-
229
- /**
230
- * The state of SSL certificate verification.
231
- */
232
- public $ssl_verification = true;
233
-
234
- /**
235
- * The proxy to use for connecting.
236
- */
237
- public $proxy = null;
238
-
239
- /**
240
- * The alternate hostname to use, if any.
241
- */
242
- public $hostname = null;
243
-
244
- /**
245
- * The state of the capability to override the hostname with <set_hostname()>.
246
- */
247
- public $override_hostname = true;
248
-
249
- /**
250
- * The alternate port number to use, if any.
251
- */
252
- public $port_number = null;
253
-
254
- /**
255
- * The alternate resource prefix to use, if any.
256
- */
257
- public $resource_prefix = null;
258
-
259
- /**
260
- * The state of cache flow usage.
261
- */
262
- public $use_cache_flow = false;
263
-
264
- /**
265
- * The caching class to use.
266
- */
267
- public $cache_class = null;
268
-
269
- /**
270
- * The caching location to use.
271
- */
272
- public $cache_location = null;
273
-
274
- /**
275
- * When the cache should be considered stale.
276
- */
277
- public $cache_expires = null;
278
-
279
- /**
280
- * The state of cache compression.
281
- */
282
- public $cache_compress = null;
283
-
284
- /**
285
- * The current instantiated cache object.
286
- */
287
- public $cache_object = null;
288
-
289
- /**
290
- * The current instantiated batch request object.
291
- */
292
- public $batch_object = null;
293
-
294
- /**
295
- * The internally instantiated batch request object.
296
- */
297
- public $internal_batch_object = null;
298
-
299
- /**
300
- * The state of batch flow usage.
301
- */
302
- public $use_batch_flow = false;
303
-
304
- /**
305
- * The state of the cache deletion setting.
306
- */
307
- public $delete_cache = false;
308
-
309
- /**
310
- * The state of the debug mode setting.
311
- */
312
- public $debug_mode = false;
313
-
314
- /**
315
- * The number of times to retry failed requests.
316
- */
317
- public $max_retries = 3;
318
-
319
- /**
320
- * The user-defined callback function to call when a stream is read from.
321
- */
322
- public $registered_streaming_read_callback = null;
323
-
324
- /**
325
- * The user-defined callback function to call when a stream is written to.
326
- */
327
- public $registered_streaming_write_callback = null;
328
-
329
- /**
330
- * The credentials to use for authentication.
331
- */
332
- public $credentials = array();
333
-
334
- /**
335
- * The authentication class to use.
336
- */
337
- public $auth_class = null;
338
-
339
- /**
340
- * The operation to execute.
341
- */
342
- public $operation = null;
343
-
344
- /**
345
- * The payload to send.
346
- */
347
- public $payload = array();
348
-
349
- /**
350
- * The string prefix to prepend to the operation name.
351
- */
352
- public $operation_prefix = '';
353
-
354
- /**
355
- * The number of times a request has been retried.
356
- */
357
- public $redirects = 0;
358
-
359
- /**
360
- * The state of whether the response should be parsed or not.
361
- */
362
- public $parse_the_response = true;
363
-
364
-
365
- /*%******************************************************************************************%*/
366
- // CONSTRUCTOR
367
-
368
- /**
369
- * The constructor. This class should not be instantiated directly. Rather, a service-specific class
370
- * should be instantiated.
371
- *
372
- * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
373
- * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
374
- * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
375
- * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
376
- * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
377
- * <li><code>instance_profile_timeout</code> - <code>integer</code> - Optional - When retrieving IAM instance profile credentials, there is a hard connection timeout that defaults to 2 seconds to prevent unnecessary on non-EC2 systems. This setting allows you to change that timeout if needed.</li>
378
- * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
379
- * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li>
380
- * <li><code>use_instance_profile_credentials</code> - <code>boolean</code> - Optional - Forces the use of IAM Instance Profile credentials, even when regular credentials are provided.</li></ul>
381
- * @return void
382
- */
383
- public function __construct(array $options = array())
384
- {
385
- // Instantiate the utilities class.
386
- $this->util = new $this->utilities_class();
387
-
388
- // Determine the current service.
389
- $this->service = get_class($this);
390
-
391
- // Create credentials based on the options
392
- $runtime_credentials = new CFCredential($options);
393
- $credentials_provided = false;
394
-
395
- // Retrieve a credential set from config.inc.php if it exists
396
- if (isset($options['credentials']))
397
- {
398
- // Use a specific credential set and merge with the runtime credentials
399
- $this->credentials = CFCredentials::get($options['credentials'])
400
- ->merge($runtime_credentials);
401
- }
402
- else
403
- {
404
- try
405
- {
406
- // Use the default credential set and merge with the runtime credentials
407
- $this->credentials = CFCredentials::get(CFCredentials::DEFAULT_KEY)
408
- ->merge($runtime_credentials);
409
- }
410
- catch (CFCredentials_Exception $e)
411
- {
412
- // Only the runtime credentials were provided
413
- $this->credentials = $runtime_credentials;
414
- }
415
- }
416
-
417
- // Check if keys were actually provided
418
- if (isset($this->credentials['key']) && isset($this->credentials['secret']))
419
- {
420
- $credentials_provided = true;
421
- }
422
-
423
- // Check for an instance profile credentials override
424
- if (isset($this->credentials['use_instance_profile_credentials']) && $this->credentials['use_instance_profile_credentials'])
425
- {
426
- $credentials_provided = false;
427
- }
428
-
429
- // Automatically enable whichever caching mechanism is set to default.
430
- $this->set_cache_config($this->credentials->default_cache_config);
431
-
432
- // If no credentials were provided, try to get them from the EC2 instance profile
433
- if (!$credentials_provided)
434
- {
435
- // Default caching mechanism is required
436
- if (!$this->credentials->default_cache_config)
437
- {
438
- // @codeCoverageIgnoreStart
439
- throw new CFCredentials_Exception('No credentials were provided. The SDK attempts to retrieve Instance '
440
- . 'Profile credentials from the EC2 Instance Metadata Service, but doing this requires the '
441
- . '"default_cache_config" option to be set in the config.inc.php file or constructor. In order to '
442
- . 'cache the retrieved credentials.');
443
- // @codeCoverageIgnoreEnd
444
- }
445
-
446
- // Instantiate and invoke the cache for instance profile credentials
447
- $cache = new $this->cache_class('instance_profile_credentials', $this->cache_location, 0, $this->cache_compress);
448
- if ($data = $cache->read())
449
- {
450
- $cache->expire_in((strtotime($data['expires']) - time()) * 0.85);
451
- }
452
- $instance_profile_credentials = $cache->response_manager(array($this, 'cache_instance_profile_credentials'), array($cache, $options));
453
-
454
- $this->credentials->key = $instance_profile_credentials['key'];
455
- $this->credentials->secret = $instance_profile_credentials['secret'];
456
- $this->credentials->token = $instance_profile_credentials['token'];
457
- }
458
-
459
- // Set internal credentials after they are resolved
460
- $this->key = $this->credentials->key;
461
- $this->secret_key = $this->credentials->secret;
462
- $this->auth_token = $this->credentials->token;
463
- }
464
-
465
- /**
466
- * Alternate approach to constructing a new instance. Supports chaining.
467
- *
468
- * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
469
- * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
470
- * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
471
- * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
472
- * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
473
- * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
474
- * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
475
- * @return void
476
- */
477
- public static function factory(array $options = array())
478
- {
479
- if (version_compare(PHP_VERSION, '5.3.0', '<'))
480
- {
481
- throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::factory().');
482
- }
483
-
484
- $self = get_called_class();
485
- return new $self($options);
486
- }
487
-
488
-
489
- /*%******************************************************************************************%*/
490
- // MAGIC METHODS
491
-
492
- /**
493
- * A magic method that allows `camelCase` method names to be translated into `snake_case` names.
494
- *
495
- * @param string $name (Required) The name of the method.
496
- * @param array $arguments (Required) The arguments passed to the method.
497
- * @return mixed The results of the intended method.
498
- */
499
- public function __call($name, $arguments)
500
- {
501
- // Convert camelCase method calls to snake_case.
502
- $method_name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
503
-
504
- if (method_exists($this, $method_name))
505
- {
506
- return call_user_func_array(array($this, $method_name), $arguments);
507
- }
508
-
509
- throw new CFRuntime_Exception('The method ' . $name . '() is undefined. Attempted to map to ' . $method_name . '() which is also undefined. Error occurred');
510
- }
511
-
512
-
513
- /*%******************************************************************************************%*/
514
- // SET CUSTOM SETTINGS
515
-
516
- /**
517
- * Set the proxy settings to use.
518
- *
519
- * @param string $proxy (Required) Accepts proxy credentials in the following format: `proxy://user:pass@hostname:port`
520
- * @return $this A reference to the current instance.
521
- */
522
- public function set_proxy($proxy)
523
- {
524
- $this->proxy = $proxy;
525
- return $this;
526
- }
527
-
528
- /**
529
- * Set the hostname to connect to. This is useful for alternate services that are API-compatible with
530
- * AWS, but run from a different hostname.
531
- *
532
- * @param string $hostname (Required) The alternate hostname to use in place of the default one. Useful for mock or test applications living on different hostnames.
533
- * @param integer $port_number (Optional) The alternate port number to use in place of the default one. Useful for mock or test applications living on different port numbers.
534
- * @return $this A reference to the current instance.
535
- */
536
- public function set_hostname($hostname, $port_number = null)
537
- {
538
- if ($this->override_hostname)
539
- {
540
- $this->hostname = $hostname;
541
-
542
- if ($port_number)
543
- {
544
- $this->port_number = $port_number;
545
- $this->hostname .= ':' . (string) $this->port_number;
546
- }
547
- }
548
-
549
- return $this;
550
- }
551
-
552
- /**
553
- * Set the resource prefix to use. This method is useful for alternate services that are API-compatible
554
- * with AWS.
555
- *
556
- * @param string $prefix (Required) An alternate prefix to prepend to the resource path. Useful for mock or test applications.
557
- * @return $this A reference to the current instance.
558
- */
559
- public function set_resource_prefix($prefix)
560
- {
561
- $this->resource_prefix = $prefix;
562
- return $this;
563
- }
564
-
565
- /**
566
- * Disables any subsequent use of the <set_hostname()> method.
567
- *
568
- * @param boolean $override (Optional) Whether or not subsequent calls to <set_hostname()> should be obeyed. A `false` value disables the further effectiveness of <set_hostname()>. Defaults to `true`.
569
- * @return $this A reference to the current instance.
570
- */
571
- public function allow_hostname_override($override = true)
572
- {
573
- $this->override_hostname = $override;
574
- return $this;
575
- }
576
-
577
- /**
578
- * Disables SSL/HTTPS connections for hosts that don't support them. Some services, however, still
579
- * require SSL support.
580
- *
581
- * This method will throw a user warning when invoked, which can be hidden by changing your
582
- * <php:error_reporting()> settings.
583
- *
584
- * @return $this A reference to the current instance.
585
- */
586
- public function disable_ssl()
587
- {
588
- trigger_error('Disabling SSL connections is potentially unsafe and highly discouraged.', E_USER_WARNING);
589
- $this->use_ssl = false;
590
- return $this;
591
- }
592
-
593
- /**
594
- * Disables the verification of the SSL Certificate Authority. Doing so can enable an attacker to carry
595
- * out a man-in-the-middle attack.
596
- *
597
- * https://secure.wikimedia.org/wikipedia/en/wiki/Man-in-the-middle_attack
598
- *
599
- * This method will throw a user warning when invoked, which can be hidden by changing your
600
- * <php:error_reporting()> settings.
601
- *
602
- * @return $this A reference to the current instance.
603
- */
604
- public function disable_ssl_verification($ssl_verification = false)
605
- {
606
- trigger_error('Disabling the verification of SSL certificates can lead to man-in-the-middle attacks. It is potentially unsafe and highly discouraged.', E_USER_WARNING);
607
- $this->ssl_verification = $ssl_verification;
608
- return $this;
609
- }
610
-
611
- /**
612
- * Enables HTTP request/response header logging to `STDERR`.
613
- *
614
- * @param boolean $enabled (Optional) Whether or not to enable debug mode. Defaults to `true`.
615
- * @return $this A reference to the current instance.
616
- */
617
- public function enable_debug_mode($enabled = true)
618
- {
619
- $this->debug_mode = $enabled;
620
- return $this;
621
- }
622
-
623
- /**
624
- * Sets the maximum number of times to retry failed requests.
625
- *
626
- * @param integer $retries (Optional) The maximum number of times to retry failed requests. Defaults to `3`.
627
- * @return $this A reference to the current instance.
628
- */
629
- public function set_max_retries($retries = 3)
630
- {
631
- $this->max_retries = $retries;
632
- return $this;
633
- }
634
-
635
- /**
636
- * Set the caching configuration to use for response caching.
637
- *
638
- * @param string $location (Required) <p>The location to store the cache object in. This may vary by cache method.</p><ul><li>File - The local file system paths such as <code>./cache</code> (relative) or <code>/tmp/cache/</code> (absolute). The location must be server-writable.</li><li>APC - Pass in <code>apc</code> to use this lightweight cache. You must have the <a href="http://php.net/apc">APC extension</a> installed.</li><li>XCache - Pass in <code>xcache</code> to use this lightweight cache. You must have the <a href="http://xcache.lighttpd.net">XCache</a> extension installed.</li><li>Memcached - Pass in an indexed array of associative arrays. Each associative array should have a <code>host</code> and a <code>port</code> value representing a <a href="http://php.net/memcached">Memcached</a> server to connect to.</li><li>PDO - A URL-style string (e.g. <code>pdo.mysql://user:pass@localhost/cache</code>) or a standard DSN-style string (e.g. <code>pdo.sqlite:/sqlite/cache.db</code>). MUST be prefixed with <code>pdo.</code>. See <code>CachePDO</code> and <a href="http://php.net/pdo">PDO</a> for more details.</li></ul>
639
- * @param boolean $gzip (Optional) Whether or not data should be gzipped before being stored. A value of `true` will compress the contents before caching them. A value of `false` will leave the contents uncompressed. Defaults to `true`.
640
- * @return $this A reference to the current instance.
641
- */
642
- public function set_cache_config($location, $gzip = true)
643
- {
644
- // If location is empty, don't do anything.
645
- if (empty($location))
646
- {
647
- return $this;
648
- }
649
-
650
- // If we have an array, we're probably passing in Memcached servers and ports.
651
- if (is_array($location))
652
- {
653
- $this->cache_class = 'CacheMC';
654
- }
655
- else
656
- {
657
- // I would expect locations like `/tmp/cache`, `pdo.mysql://user:pass@hostname:port`, `pdo.sqlite:memory:`, and `apc`.
658
- $type = strtolower(substr($location, 0, 3));
659
- switch ($type)
660
- {
661
- case 'apc':
662
- $this->cache_class = 'CacheAPC';
663
- break;
664
-
665
- case 'xca': // First three letters of `xcache`
666
- $this->cache_class = 'CacheXCache';
667
- break;
668
-
669
- case 'pdo':
670
- $this->cache_class = 'CachePDO';
671
- $location = substr($location, 4);
672
- break;
673
-
674
- default:
675
- $this->cache_class = 'CacheFile';
676
- break;
677
- }
678
- }
679
-
680
- // Set the remaining cache information.
681
- $this->cache_location = $location;
682
- $this->cache_compress = $gzip;
683
-
684
- return $this;
685
- }
686
-
687
- /**
688
- * Register a callback function to execute whenever a data stream is read from using
689
- * <CFRequest::streaming_read_callback()>.
690
- *
691
- * The user-defined callback function should accept three arguments:
692
- *
693
- * <ul>
694
- * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
695
- * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
696
- * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
697
- * </ul>
698
- *
699
- * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
700
- * <li>The name of a global function to execute, passed as a string.</li>
701
- * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
702
- * <li>An anonymous function (PHP 5.3+).</li></ul>
703
- * @return $this A reference to the current instance.
704
- */
705
- public function register_streaming_read_callback($callback)
706
- {
707
- $this->registered_streaming_read_callback = $callback;
708
- return $this;
709
- }
710
-
711
- /**
712
- * Register a callback function to execute whenever a data stream is written to using
713
- * <CFRequest::streaming_write_callback()>.
714
- *
715
- * The user-defined callback function should accept two arguments:
716
- *
717
- * <ul>
718
- * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
719
- * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
720
- * </ul>
721
- *
722
- * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
723
- * <li>The name of a global function to execute, passed as a string.</li>
724
- * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
725
- * <li>An anonymous function (PHP 5.3+).</li></ul>
726
- * @return $this A reference to the current instance.
727
- */
728
- public function register_streaming_write_callback($callback)
729
- {
730
- $this->registered_streaming_write_callback = $callback;
731
- return $this;
732
- }
733
-
734
- /**
735
- * Fetches and caches STS credentials. This is meant to be used by the constructor, and is not to be
736
- * manually invoked.
737
- *
738
- * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
739
- * @param array $options (Required) The options that were passed into the constructor.
740
- * @return mixed The data to be cached, or NULL.
741
- */
742
- public function cache_sts_credentials($cache, $options)
743
- {
744
- $token = new AmazonSTS($options);
745
- $response = $token->get_session_token();
746
-
747
- if ($response->isOK())
748
- {
749
- // Update the expiration
750
- $expiration_time = strtotime((string) $response->body->GetSessionTokenResult->Credentials->Expiration);
751
- $expiration_duration = round(($expiration_time - time()) * 0.85);
752
- $cache->expire_in($expiration_duration);
753
-
754
- // Return the important data
755
- $credentials = $response->body->GetSessionTokenResult->Credentials;
756
-
757
- return array(
758
- 'key' => (string) $credentials->AccessKeyId,
759
- 'secret' => (string) $credentials->SecretAccessKey,
760
- 'token' => (string) $credentials->SessionToken,
761
- 'expires' => (string) $credentials->Expiration,
762
- );
763
- }
764
-
765
- // @codeCoverageIgnoreStart
766
- throw new STS_Exception('Temporary credentials from the AWS Security '
767
- . 'Token Service could not be retrieved using the provided long '
768
- . 'term credentials. It\'s possible that the provided long term '
769
- . 'credentials were invalid.');
770
- // @codeCoverageIgnoreEnd
771
- }
772
-
773
- /**
774
- * Fetches and caches EC2 instance profile credentials. This is meant to be used by the constructor, and is not to
775
- * be manually invoked.
776
- *
777
- * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
778
- * @param array $options (Required) The options that were passed into the constructor.
779
- * @return mixed The data to be cached, or NULL.
780
- */
781
- public function cache_instance_profile_credentials($cache, $options)
782
- {
783
- $instance_profile_url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/';
784
- $connect_timeout = isset($options['instance_profile_timeout']) ? $options['instance_profile_timeout'] : 2;
785
-
786
- try
787
- {
788
- // Make a call to the EC2 Metadata Service to find the available instance profile
789
- $request = new RequestCore($instance_profile_url);
790
- $request->set_curlopts(array(CURLOPT_CONNECTTIMEOUT => $connect_timeout));
791
- $response = $request->send_request(true);
792
-
793
- if ($response->isOK())
794
- {
795
- // Get the instance profile name
796
- $profile = (string) $response->body;
797
-
798
- // Make a call to the EC2 Metadata Service to get the instance profile credentials
799
- $request = new RequestCore($instance_profile_url . $profile);
800
- $request->set_curlopts(array(CURLOPT_CONNECTTIMEOUT => $connect_timeout));
801
- $response = $request->send_request(true);
802
-
803
- if ($response->isOK())
804
- {
805
- // Get the credentials
806
- $credentials = json_decode($response->body, true);
807
-
808
- if ($credentials['Code'] === 'Success')
809
- {
810
- // Determine the expiration time
811
- $expiration_time = strtotime((string) $credentials['Expiration']);
812
- $expiration_duration = round(($expiration_time - time()) * 0.85);
813
- $cache->expire_in($expiration_duration);
814
-
815
- // Return the credential information
816
- return array(
817
- 'key' => $credentials['AccessKeyId'],
818
- 'secret' => $credentials['SecretAccessKey'],
819
- 'token' => $credentials['Token'],
820
- 'expires' => $credentials['Expiration'],
821
- );
822
- }
823
- }
824
- }
825
- }
826
- catch (cURL_Exception $e)
827
- {
828
- // The EC2 Metadata Service does not exist or had timed out.
829
- // An exception will be thrown on the next line.
830
- }
831
-
832
- // @codeCoverageIgnoreStart
833
- throw new CFCredentials_Exception('No credentials were provided. The SDK attempted to retrieve Instance '
834
- . 'Profile credentials from the EC2 Instance Metadata Service, but failed to do so. Instance profile '
835
- . 'credentials are only accessible on EC2 instances configured with a specific IAM role.');
836
- // @codeCoverageIgnoreEnd
837
- }
838
-
839
-
840
- /*%******************************************************************************************%*/
841
- // SET CUSTOM CLASSES
842
-
843
- /**
844
- * Set a custom class for this functionality. Use this method when extending/overriding existing classes
845
- * with new functionality.
846
- *
847
- * The replacement class must extend from <CFUtilities>.
848
- *
849
- * @param string $class (Optional) The name of the new class to use for this functionality.
850
- * @return $this A reference to the current instance.
851
- */
852
- public function set_utilities_class($class = 'CFUtilities')
853
- {
854
- $this->utilities_class = $class;
855
- $this->util = new $this->utilities_class();
856
- return $this;
857
- }
858
-
859
- /**
860
- * Set a custom class for this functionality. Use this method when extending/overriding existing classes
861
- * with new functionality.
862
- *
863
- * The replacement class must extend from <CFRequest>.
864
- *
865
- * @param string $class (Optional) The name of the new class to use for this functionality.
866
- * @param $this A reference to the current instance.
867
- */
868
- public function set_request_class($class = 'CFRequest')
869
- {
870
- $this->request_class = $class;
871
- return $this;
872
- }
873
-
874
- /**
875
- * Set a custom class for this functionality. Use this method when extending/overriding existing classes
876
- * with new functionality.
877
- *
878
- * The replacement class must extend from <CFResponse>.
879
- *
880
- * @param string $class (Optional) The name of the new class to use for this functionality.
881
- * @return $this A reference to the current instance.
882
- */
883
- public function set_response_class($class = 'CFResponse')
884
- {
885
- $this->response_class = $class;
886
- return $this;
887
- }
888
-
889
- /**
890
- * Set a custom class for this functionality. Use this method when extending/overriding existing classes
891
- * with new functionality.
892
- *
893
- * The replacement class must extend from <CFSimpleXML>.
894
- *
895
- * @param string $class (Optional) The name of the new class to use for this functionality.
896
- * @return $this A reference to the current instance.
897
- */
898
- public function set_parser_class($class = 'CFSimpleXML')
899
- {
900
- $this->parser_class = $class;
901
- return $this;
902
- }
903
-
904
- /**
905
- * Set a custom class for this functionality. Use this method when extending/overriding existing classes
906
- * with new functionality.
907
- *
908
- * The replacement class must extend from <CFBatchRequest>.
909
- *
910
- * @param string $class (Optional) The name of the new class to use for this functionality.
911
- * @return $this A reference to the current instance.
912
- */
913
- public function set_batch_class($class = 'CFBatchRequest')
914
- {
915
- $this->batch_class = $class;
916
- return $this;
917
- }
918
-
919
-
920
- /*%******************************************************************************************%*/
921
- // AUTHENTICATION
922
-
923
- /**
924
- * Default, shared method for authenticating a connection to AWS.
925
- *
926
- * @param string $operation (Required) Indicates the operation to perform.
927
- * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
928
- * @return CFResponse Object containing a parsed HTTP response.
929
- */
930
- public function authenticate($operation, $payload)
931
- {
932
- $original_payload = $payload;
933
- $method_arguments = func_get_args();
934
- $curlopts = array();
935
- $return_curl_handle = false;
936
-
937
- if (substr($operation, 0, strlen($this->operation_prefix)) !== $this->operation_prefix)
938
- {
939
- $operation = $this->operation_prefix . $operation;
940
- }
941
-
942
- // Extract the custom CURLOPT settings from the payload
943
- if (is_array($payload) && isset($payload['curlopts']))
944
- {
945
- $curlopts = $payload['curlopts'];
946
- unset($payload['curlopts']);
947
- }
948
-
949
- // Determine whether the response or curl handle should be returned
950
- if (is_array($payload) && isset($payload['returnCurlHandle']))
951
- {
952
- $return_curl_handle = isset($payload['returnCurlHandle']) ? $payload['returnCurlHandle'] : false;
953
- unset($payload['returnCurlHandle']);
954
- }
955
-
956
- // Use the caching flow to determine if we need to do a round-trip to the server.
957
- if ($this->use_cache_flow)
958
- {
959
- // Generate an identifier specific to this particular set of arguments.
960
- $cache_id = $this->key . '_' . get_class($this) . '_' . $operation . '_' . sha1(serialize($method_arguments));
961
-
962
- // Instantiate the appropriate caching object.
963
- $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
964
-
965
- if ($this->delete_cache)
966
- {
967
- $this->use_cache_flow = false;
968
- $this->delete_cache = false;
969
- return $this->cache_object->delete();
970
- }
971
-
972
- // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
973
- $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
974
-
975
- // Parse the XML body
976
- $data = $this->parse_callback($data);
977
-
978
- // End!
979
- return $data;
980
- }
981
-
982
- /*%******************************************************************************************%*/
983
-
984
- // Signer
985
- $signer = new $this->auth_class($this->hostname, $operation, $payload, $this->credentials);
986
- $signer->key = $this->key;
987
- $signer->secret_key = $this->secret_key;
988
- $signer->auth_token = $this->auth_token;
989
- $signer->api_version = $this->api_version;
990
- $signer->utilities_class = $this->utilities_class;
991
- $signer->request_class = $this->request_class;
992
- $signer->response_class = $this->response_class;
993
- $signer->use_ssl = $this->use_ssl;
994
- $signer->proxy = $this->proxy;
995
- $signer->util = $this->util;
996
- $signer->registered_streaming_read_callback = $this->registered_streaming_read_callback;
997
- $signer->registered_streaming_write_callback = $this->registered_streaming_write_callback;
998
- $request = $signer->authenticate();
999
-
1000
- // Update RequestCore settings
1001
- $request->request_class = $this->request_class;
1002
- $request->response_class = $this->response_class;
1003
- $request->ssl_verification = $this->ssl_verification;
1004
-
1005
- /*%******************************************************************************************%*/
1006
-
1007
- // Debug mode
1008
- if ($this->debug_mode)
1009
- {
1010
- $request->debug_mode = $this->debug_mode;
1011
- }
1012
-
1013
- // Set custom CURLOPT settings
1014
- if (count($curlopts))
1015
- {
1016
- $request->set_curlopts($curlopts);
1017
- }
1018
-
1019
- // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
1020
- if ($this->use_batch_flow)
1021
- {
1022
- $handle = $request->prep_request();
1023
- $this->batch_object->add($handle);
1024
- $this->use_batch_flow = false;
1025
-
1026
- return $handle;
1027
- }
1028
- elseif ($return_curl_handle)
1029
- {
1030
- return $request->prep_request();
1031
- }
1032
-
1033
- // Send!
1034
- $request->send_request();
1035
-
1036
- // Prepare the response.
1037
- $headers = $request->get_response_header();
1038
- $headers['x-aws-stringtosign'] = $signer->string_to_sign;
1039
-
1040
- if (isset($signer->canonical_request))
1041
- {
1042
- $headers['x-aws-canonicalrequest'] = $signer->canonical_request;
1043
- }
1044
-
1045
- $headers['x-aws-request-headers'] = $request->request_headers;
1046
- $headers['x-aws-body'] = $signer->querystring;
1047
-
1048
- $data = new $this->response_class($headers, ($this->parse_the_response === true) ? $this->parse_callback($request->get_response_body()) : $request->get_response_body(), $request->get_response_code());
1049
-
1050
- // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
1051
- if (
1052
- (integer) $request->get_response_code() === 500 || // Internal Error (presumably transient)
1053
- (integer) $request->get_response_code() === 503) // Service Unavailable (presumably transient)
1054
- {
1055
- if ($this->redirects <= $this->max_retries)
1056
- {
1057
- // Exponential backoff
1058
- $delay = (integer) (pow(4, $this->redirects) * 100000);
1059
- usleep($delay);
1060
- $this->redirects++;
1061
- $data = $this->authenticate($operation, $original_payload);
1062
- }
1063
- }
1064
-
1065
- // DynamoDB has custom logic
1066
- elseif (
1067
- (integer) $request->get_response_code() === 400 &&
1068
- stripos((string) $request->get_response_body(), 'com.amazonaws.dynamodb.') !== false && (
1069
- stripos((string) $request->get_response_body(), 'ProvisionedThroughputExceededException') !== false
1070
- )
1071
- )
1072
- {
1073
- if ($this->redirects === 0)
1074
- {
1075
- $this->redirects++;
1076
- $data = $this->authenticate($operation, $original_payload);
1077
- }
1078
- elseif ($this->redirects <= max($this->max_retries, 10))
1079
- {
1080
- // Exponential backoff
1081
- $delay = (integer) (pow(2, ($this->redirects - 1)) * 50000);
1082
- usleep($delay);
1083
- $this->redirects++;
1084
- $data = $this->authenticate($operation, $original_payload);
1085
- }
1086
- }
1087
-
1088
- $this->redirects = 0;
1089
- return $data;
1090
- }
1091
-
1092
-
1093
- /*%******************************************************************************************%*/
1094
- // BATCH REQUEST LAYER
1095
-
1096
- /**
1097
- * Specifies that the intended request should be queued for a later batch request.
1098
- *
1099
- * @param CFBatchRequest $queue (Optional) The <CFBatchRequest> instance to use for managing batch requests. If not available, it generates a new instance of <CFBatchRequest>.
1100
- * @return $this A reference to the current instance.
1101
- */
1102
- public function batch(CFBatchRequest &$queue = null)
1103
- {
1104
- if ($queue)
1105
- {
1106
- $this->batch_object = $queue;
1107
- }
1108
- elseif ($this->internal_batch_object)
1109
- {
1110
- $this->batch_object = &$this->internal_batch_object;
1111
- }
1112
- else
1113
- {
1114
- $this->internal_batch_object = new $this->batch_class();
1115
- $this->batch_object = &$this->internal_batch_object;
1116
- }
1117
-
1118
- $this->use_batch_flow = true;
1119
-
1120
- return $this;
1121
- }
1122
-
1123
- /**
1124
- * Executes the batch request queue by sending all queued requests.
1125
- *
1126
- * @param boolean $clear_after_send (Optional) Whether or not to clear the batch queue after sending a request. Defaults to `true`. Set this to `false` if you are caching batch responses and want to retrieve results later.
1127
- * @return array An array of <CFResponse> objects.
1128
- */
1129
- public function send($clear_after_send = true)
1130
- {
1131
- if ($this->use_batch_flow)
1132
- {
1133
- // When we send the request, disable batch flow.
1134
- $this->use_batch_flow = false;
1135
-
1136
- // If we're not caching, simply send the request.
1137
- if (!$this->use_cache_flow)
1138
- {
1139
- $response = $this->batch_object->send();
1140
- $parsed_data = array_map(array($this, 'parse_callback'), $response);
1141
- $parsed_data = new CFArray($parsed_data);
1142
-
1143
- // Clear the queue
1144
- if ($clear_after_send)
1145
- {
1146
- $this->batch_object->queue = array();
1147
- }
1148
-
1149
- return $parsed_data;
1150
- }
1151
-
1152
- // Generate an identifier specific to this particular set of arguments.
1153
- $cache_id = $this->key . '_' . get_class($this) . '_' . sha1(serialize($this->batch_object));
1154
-
1155
- // Instantiate the appropriate caching object.
1156
- $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
1157
-
1158
- if ($this->delete_cache)
1159
- {
1160
- $this->use_cache_flow = false;
1161
- $this->delete_cache = false;
1162
- return $this->cache_object->delete();
1163
- }
1164
-
1165
- // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
1166
- $data_set = $this->cache_object->response_manager(array($this, 'cache_callback_batch'), array($this->batch_object));
1167
- $parsed_data = array_map(array($this, 'parse_callback'), $data_set);
1168
- $parsed_data = new CFArray($parsed_data);
1169
-
1170
- // Clear the queue
1171
- if ($clear_after_send)
1172
- {
1173
- $this->batch_object->queue = array();
1174
- }
1175
-
1176
- // End!
1177
- return $parsed_data;
1178
- }
1179
-
1180
- // Load the class
1181
- $null = new CFBatchRequest();
1182
- unset($null);
1183
-
1184
- throw new CFBatchRequest_Exception('You must use $object->batch()->send()');
1185
- }
1186
-
1187
- /**
1188
- * Parses a response body into a PHP object if appropriate.
1189
- *
1190
- * @param CFResponse|string $response (Required) The <CFResponse> object to parse, or an XML string that would otherwise be a response body.
1191
- * @param string $content_type (Optional) The content-type to use when determining how to parse the content.
1192
- * @return CFResponse|string A parsed <CFResponse> object, or parsed XML.
1193
- */
1194
- public function parse_callback($response, $headers = null)
1195
- {
1196
- // Bail out
1197
- if (!$this->parse_the_response) return $response;
1198
-
1199
- // Shorten this so we have a (mostly) single code path
1200
- if (isset($response->body))
1201
- {
1202
- if (is_string($response->body))
1203
- {
1204
- $body = $response->body;
1205
- }
1206
- else
1207
- {
1208
- return $response;
1209
- }
1210
- }
1211
- elseif (is_string($response))
1212
- {
1213
- $body = $response;
1214
- }
1215
- else
1216
- {
1217
- return $response;
1218
- }
1219
-
1220
- // Decompress gzipped content
1221
- if (isset($headers['content-encoding']))
1222
- {
1223
- switch (strtolower(trim($headers['content-encoding'], "\x09\x0A\x0D\x20")))
1224
- {
1225
- case 'gzip':
1226
- case 'x-gzip':
1227
- $decoder = new CFGzipDecode($body);
1228
- if ($decoder->parse())
1229
- {
1230
- $body = $decoder->data;
1231
- }
1232
- break;
1233
-
1234
- case 'deflate':
1235
- if (($uncompressed = gzuncompress($body)) !== false)
1236
- {
1237
- $body = $uncompressed;
1238
- }
1239
- elseif (($uncompressed = gzinflate($body)) !== false)
1240
- {
1241
- $body = $uncompressed;
1242
- }
1243
- break;
1244
- }
1245
- }
1246
-
1247
- // Look for XML cues
1248
- if (
1249
- (isset($headers['content-type']) && ($headers['content-type'] === 'text/xml' || $headers['content-type'] === 'application/xml')) || // We know it's XML
1250
- (!isset($headers['content-type']) && (stripos($body, '<?xml') === 0 || strpos($body, '<Error>') === 0) || preg_match('/^<(\w*) xmlns="http(s?):\/\/(\w*).amazon(aws)?.com/im', $body)) // Sniff for XML
1251
- )
1252
- {
1253
- // Strip the default XML namespace to simplify XPath expressions
1254
- $body = str_replace("xmlns=", "ns=", $body);
1255
-
1256
- try {
1257
- // Parse the XML body
1258
- $body = new $this->parser_class($body);
1259
- }
1260
- catch (Exception $e)
1261
- {
1262
- throw new Parser_Exception($e->getMessage());
1263
- }
1264
- }
1265
- // Look for JSON cues
1266
- elseif (
1267
- (isset($headers['content-type']) && ($headers['content-type'] === 'application/json') || $headers['content-type'] === 'application/x-amz-json-1.0') || // We know it's JSON
1268
- (!isset($headers['content-type']) && $this->util->is_json($body)) // Sniff for JSON
1269
- )
1270
- {
1271
- // Normalize JSON to a CFSimpleXML object
1272
- $body = CFJSON::to_xml($body, $this->parser_class);
1273
- }
1274
-
1275
- // Put the parsed data back where it goes
1276
- if (isset($response->body))
1277
- {
1278
- $response->body = $body;
1279
- }
1280
- else
1281
- {
1282
- $response = $body;
1283
- }
1284
-
1285
- return $response;
1286
- }
1287
-
1288
-
1289
- /*%******************************************************************************************%*/
1290
- // CACHING LAYER
1291
-
1292
- /**
1293
- * Specifies that the resulting <CFResponse> object should be cached according to the settings from
1294
- * <set_cache_config()>.
1295
- *
1296
- * @param string|integer $expires (Required) The time the cache is to expire. Accepts a number of seconds as an integer, or an amount of time, as a string, that is understood by <php:strtotime()> (e.g. "1 hour").
1297
- * @param $this A reference to the current instance.
1298
- * @return $this
1299
- */
1300
- public function cache($expires)
1301
- {
1302
- // Die if they haven't used set_cache_config().
1303
- if (!$this->cache_class)
1304
- {
1305
- throw new CFRuntime_Exception('Must call set_cache_config() before using cache()');
1306
- }
1307
-
1308
- if (is_string($expires))
1309
- {
1310
- $expires = strtotime($expires);
1311
- $this->cache_expires = $expires - time();
1312
- }
1313
- elseif (is_int($expires))
1314
- {
1315
- $this->cache_expires = $expires;
1316
- }
1317
-
1318
- $this->use_cache_flow = true;
1319
-
1320
- return $this;
1321
- }
1322
-
1323
- /**
1324
- * The callback function that is executed when the cache doesn't exist or has expired. The response of
1325
- * this method is cached. Accepts identical parameters as the <authenticate()> method. Never call this
1326
- * method directly -- it is used internally by the caching system.
1327
- *
1328
- * @param string $operation (Required) Indicates the operation to perform.
1329
- * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
1330
- * @return CFResponse A parsed HTTP response.
1331
- */
1332
- public function cache_callback($operation, $payload)
1333
- {
1334
- // Disable the cache flow since it's already been handled.
1335
- $this->use_cache_flow = false;
1336
-
1337
- // Make the request
1338
- $response = $this->authenticate($operation, $payload);
1339
-
1340
- // If this is an XML document, convert it back to a string.
1341
- if (isset($response->body) && ($response->body instanceof SimpleXMLElement))
1342
- {
1343
- $response->body = $response->body->asXML();
1344
- }
1345
-
1346
- return $response;
1347
- }
1348
-
1349
- /**
1350
- * Used for caching the results of a batch request. Never call this method directly; it is used
1351
- * internally by the caching system.
1352
- *
1353
- * @param CFBatchRequest $batch (Required) The batch request object to send.
1354
- * @return CFResponse A parsed HTTP response.
1355
- */
1356
- public function cache_callback_batch(CFBatchRequest $batch)
1357
- {
1358
- return $batch->send();
1359
- }
1360
-
1361
- /**
1362
- * Deletes a cached <CFResponse> object using the specified cache storage type.
1363
- *
1364
- * @return boolean A value of `true` if cached object exists and is successfully deleted, otherwise `false`.
1365
- */
1366
- public function delete_cache()
1367
- {
1368
- $this->use_cache_flow = true;
1369
- $this->delete_cache = true;
1370
-
1371
- return $this;
1372
- }
1373
- }
1374
-
1375
-
1376
- /**
1377
- * Contains the functionality for auto-loading service classes.
1378
- */
1379
- class CFLoader
1380
- {
1381
- /*%******************************************************************************************%*/
1382
- // AUTO-LOADER
1383
-
1384
- /**
1385
- * Automatically load classes that aren't included.
1386
- *
1387
- * @param string $class (Required) The classname to load.
1388
- * @return boolean Whether or not the file was successfully loaded.
1389
- */
1390
- public static function autoloader($class)
1391
- {
1392
- $path = dirname(__FILE__) . DIRECTORY_SEPARATOR;
1393
-
1394
- // Amazon SDK classes
1395
- if (strstr($class, 'Amazon'))
1396
- {
1397
- if (file_exists($require_this = $path . 'services' . DIRECTORY_SEPARATOR . str_ireplace('Amazon', '', strtolower($class)) . '.class.php'))
1398
- {
1399
- require_once $require_this;
1400
- return true;
1401
- }
1402
-
1403
- return false;
1404
- }
1405
-
1406
- // Utility classes
1407
- elseif (strstr($class, 'CF'))
1408
- {
1409
- if (file_exists($require_this = $path . 'utilities' . DIRECTORY_SEPARATOR . str_ireplace('CF', '', strtolower($class)) . '.class.php'))
1410
- {
1411
- require_once $require_this;
1412
- return true;
1413
- }
1414
-
1415
- return false;
1416
- }
1417
-
1418
- // Load CacheCore
1419
- elseif (strstr($class, 'Cache'))
1420
- {
1421
- if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'cachecore' . DIRECTORY_SEPARATOR . strtolower($class) . '.class.php'))
1422
- {
1423
- require_once $require_this;
1424
- return true;
1425
- }
1426
-
1427
- return false;
1428
- }
1429
-
1430
- // Load RequestCore
1431
- elseif (strstr($class, 'RequestCore') || strstr($class, 'ResponseCore'))
1432
- {
1433
- if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'requestcore' . DIRECTORY_SEPARATOR . 'requestcore.class.php'))
1434
- {
1435
- require_once $require_this;
1436
- return true;
1437
- }
1438
-
1439
- return false;
1440
- }
1441
-
1442
- // Load Transmogrifier
1443
- elseif (strstr($class, 'Transmogrifier'))
1444
- {
1445
- if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'dom' . DIRECTORY_SEPARATOR . 'Transmogrifier.php'))
1446
- {
1447
- require_once $require_this;
1448
- return true;
1449
- }
1450
-
1451
- return false;
1452
- }
1453
-
1454
- // Load Authentication Signers
1455
- elseif (strstr($class, 'Auth'))
1456
- {
1457
- if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . str_replace('auth', 'signature_', strtolower($class)) . '.class.php'))
1458
- {
1459
- require_once $require_this;
1460
- return true;
1461
- }
1462
-
1463
- return false;
1464
- }
1465
-
1466
- // Load Signer interface
1467
- elseif ($class === 'Signer')
1468
- {
1469
- if (!interface_exists('Signable', false) &&
1470
- file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signable.interface.php'))
1471
- {
1472
- require_once $require_this;
1473
- }
1474
-
1475
- if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signer.abstract.php'))
1476
- {
1477
- require_once $require_this;
1478
- return true;
1479
- }
1480
-
1481
- return false;
1482
- }
1483
-
1484
- // Load Symfony YAML classes
1485
- elseif (strstr($class, 'sfYaml'))
1486
- {
1487
- if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'yaml' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sfYaml.php'))
1488
- {
1489
- require_once $require_this;
1490
- return true;
1491
- }
1492
-
1493
- return false;
1494
- }
1495
-
1496
- return false;
1497
- }
1498
- }
1499
-
1500
- // Register the autoloader.
1501
- spl_autoload_register(array('CFLoader', 'autoloader'));
1502
-
1503
-
1504
- /*%******************************************************************************************%*/
1505
- // CONFIGURATION
1506
-
1507
- // Look for include file in the same directory (e.g. `./config.inc.php`).
1508
- if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php'))
1509
- {
1510
- include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php';
1511
- }
1512
- // Fallback to `~/.aws/sdk/config.inc.php`
1513
- else
1514
- {
1515
- if (!isset($_ENV['HOME']) && isset($_SERVER['HOME']))
1516
- {
1517
- $_ENV['HOME'] = $_SERVER['HOME'];
1518
- }
1519
- elseif (!isset($_ENV['HOME']) && !isset($_SERVER['HOME']))
1520
- {
1521
- $os = strtolower(PHP_OS);
1522
- if (in_array($os, array('windows', 'winnt', 'win32')))
1523
- {
1524
- $_ENV['HOME'] = false;
1525
- }
1526
- else
1527
- {
1528
- $_ENV['HOME'] = `cd ~ && pwd`;
1529
- }
1530
-
1531
- if (!$_ENV['HOME'])
1532
- {
1533
- switch ($os)
1534
- {
1535
- case 'darwin':
1536
- $_ENV['HOME'] = '/Users/' . get_current_user();
1537
- break;
1538
-
1539
- case 'windows':
1540
- case 'winnt':
1541
- case 'win32':
1542
- $_ENV['HOME'] = 'c:' . DIRECTORY_SEPARATOR . 'Documents and Settings' . DIRECTORY_SEPARATOR . get_current_user();
1543
- break;
1544
-
1545
- default:
1546
- $_ENV['HOME'] = '/home/' . get_current_user();
1547
- break;
1548
- }
1549
- }
1550
- }
1551
-
1552
- if (getenv('HOME') && file_exists(getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php'))
1553
- {
1554
- include_once getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php';
1555
- }
1556
- }
1
+ <?php
2
+ /*
3
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License").
6
+ * You may not use this file except in compliance with the License.
7
+ * A copy of the License is located at
8
+ *
9
+ * http://aws.amazon.com/apache2.0
10
+ *
11
+ * or in the "license" file accompanying this file. This file is distributed
12
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13
+ * express or implied. See the License for the specific language governing
14
+ * permissions and limitations under the License.
15
+ */
16
+
17
+
18
+ /*%******************************************************************************************%*/
19
+ // EXCEPTIONS
20
+
21
+ /**
22
+ * Default CFRuntime Exception.
23
+ */
24
+ class CFRuntime_Exception extends Exception {}
25
+
26
+ /**
27
+ * Parsing Exception.
28
+ */
29
+ class Parser_Exception extends Exception {}
30
+
31
+
32
+ /*%******************************************************************************************%*/
33
+ // DETERMINE WHAT ENVIRONMENT DATA TO ADD TO THE USERAGENT FOR METRIC TRACKING
34
+
35
+ /*
36
+ Define a temporary callback function for this calculation. Get the PHP version and any
37
+ required/optional extensions that are leveraged.
38
+
39
+ Tracking this data gives Amazon better metrics about what configurations are being used
40
+ so that forward-looking plans for the code can be made with more certainty (e.g. What
41
+ version of PHP are most people running? Do they tend to have the latest PCRE?).
42
+ */
43
+ function __aws_sdk_ua_callback()
44
+ {
45
+ $ua_append = '';
46
+ $extensions = get_loaded_extensions();
47
+ $sorted_extensions = array();
48
+
49
+ if ($extensions)
50
+ {
51
+ foreach ($extensions as $extension)
52
+ {
53
+ if ($extension === 'curl' && function_exists('curl_version'))
54
+ {
55
+ $curl_version = curl_version();
56
+ $sorted_extensions[strtolower($extension)] = $curl_version['version'];
57
+ }
58
+ elseif ($extension === 'pcre' && defined('PCRE_VERSION'))
59
+ {
60
+ $pcre_version = explode(' ', PCRE_VERSION);
61
+ $sorted_extensions[strtolower($extension)] = $pcre_version[0];
62
+ }
63
+ elseif ($extension === 'openssl' && defined('OPENSSL_VERSION_TEXT'))
64
+ {
65
+ $openssl_version = explode(' ', OPENSSL_VERSION_TEXT);
66
+ $sorted_extensions[strtolower($extension)] = $openssl_version[1];
67
+ }
68
+ else
69
+ {
70
+ $sorted_extensions[strtolower($extension)] = phpversion($extension);
71
+ }
72
+ }
73
+ }
74
+
75
+ foreach (array('simplexml', 'json', 'pcre', 'spl', 'curl', 'openssl', 'apc', 'xcache', 'memcache', 'memcached', 'pdo', 'pdo_sqlite', 'sqlite', 'sqlite3', 'zlib', 'xdebug') as $ua_ext)
76
+ {
77
+ if (isset($sorted_extensions[$ua_ext]) && $sorted_extensions[$ua_ext])
78
+ {
79
+ $ua_append .= ' ' . $ua_ext . '/' . $sorted_extensions[$ua_ext];
80
+ }
81
+ elseif (isset($sorted_extensions[$ua_ext]))
82
+ {
83
+ $ua_append .= ' ' . $ua_ext . '/0';
84
+ }
85
+ }
86
+
87
+ foreach (array('memory_limit', 'date.timezone', 'open_basedir', 'safe_mode', 'zend.enable_gc') as $cfg)
88
+ {
89
+ $cfg_value = ini_get($cfg);
90
+
91
+ if (in_array($cfg, array('memory_limit', 'date.timezone'), true))
92
+ {
93
+ $ua_append .= ' ' . $cfg . '/' . str_replace('/', '.', $cfg_value);
94
+ }
95
+ elseif (in_array($cfg, array('open_basedir', 'safe_mode', 'zend.enable_gc'), true))
96
+ {
97
+ if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
98
+ {
99
+ $cfg_value = 'off';
100
+ }
101
+ elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
102
+ {
103
+ $cfg_value = 'on';
104
+ }
105
+
106
+ $ua_append .= ' ' . $cfg . '/' . $cfg_value;
107
+ }
108
+ }
109
+
110
+ return $ua_append;
111
+ }
112
+
113
+
114
+ /*%******************************************************************************************%*/
115
+ // INTERMEDIARY CONSTANTS
116
+
117
+ define('CFRUNTIME_NAME', 'aws-sdk-php');
118
+ define('CFRUNTIME_VERSION', '1.5.14');
119
+ define('CFRUNTIME_BUILD', '20120831150000');
120
+ define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . str_replace(' ', '_', php_uname('s')) . '/' . str_replace(' ', '_', php_uname('r')) . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
121
+
122
+
123
+ /*%******************************************************************************************%*/
124
+ // CLASS
125
+
126
+ /**
127
+ * Core functionality and default settings shared across all SDK classes. All methods and properties in this
128
+ * class are inherited by the service-specific classes.
129
+ *
130
+ * @version 2012.05.25
131
+ * @license See the included NOTICE.md file for more information.
132
+ * @copyright See the included NOTICE.md file for more information.
133
+ * @link http://aws.amazon.com/php/ PHP Developer Center
134
+ */
135
+ class CFRuntime
136
+ {
137
+ /*%******************************************************************************************%*/
138
+ // CONSTANTS
139
+
140
+ /**
141
+ * Name of the software.
142
+ */
143
+ const NAME = CFRUNTIME_NAME;
144
+
145
+ /**
146
+ * Version of the software.
147
+ */
148
+ const VERSION = CFRUNTIME_VERSION;
149
+
150
+ /**
151
+ * Build ID of the software.
152
+ */
153
+ const BUILD = CFRUNTIME_BUILD;
154
+
155
+ /**
156
+ * User agent string used to identify the software.
157
+ */
158
+ const USERAGENT = CFRUNTIME_USERAGENT;
159
+
160
+
161
+ /*%******************************************************************************************%*/
162
+ // PROPERTIES
163
+
164
+ /**
165
+ * The Amazon API Key.
166
+ */
167
+ public $key;
168
+
169
+ /**
170
+ * The Amazon API Secret Key.
171
+ */
172
+ public $secret_key;
173
+
174
+ /**
175
+ * The Amazon Authentication Token.
176
+ */
177
+ public $auth_token;
178
+
179
+ /**
180
+ * Handle for the utility functions.
181
+ */
182
+ public $util;
183
+
184
+ /**
185
+ * An identifier for the current AWS service.
186
+ */
187
+ public $service = null;
188
+
189
+ /**
190
+ * The supported API version.
191
+ */
192
+ public $api_version = null;
193
+
194
+ /**
195
+ * The state of whether auth should be handled as AWS Query.
196
+ */
197
+ public $use_aws_query = true;
198
+
199
+ /**
200
+ * The default class to use for utilities (defaults to <CFUtilities>).
201
+ */
202
+ public $utilities_class = 'CFUtilities';
203
+
204
+ /**
205
+ * The default class to use for HTTP requests (defaults to <CFRequest>).
206
+ */
207
+ public $request_class = 'CFRequest';
208
+
209
+ /**
210
+ * The default class to use for HTTP responses (defaults to <CFResponse>).
211
+ */
212
+ public $response_class = 'CFResponse';
213
+
214
+ /**
215
+ * The default class to use for parsing XML (defaults to <CFSimpleXML>).
216
+ */
217
+ public $parser_class = 'CFSimpleXML';
218
+
219
+ /**
220
+ * The default class to use for handling batch requests (defaults to <CFBatchRequest>).
221
+ */
222
+ public $batch_class = 'CFBatchRequest';
223
+
224
+ /**
225
+ * The state of SSL/HTTPS use.
226
+ */
227
+ public $use_ssl = true;
228
+
229
+ /**
230
+ * The state of SSL certificate verification.
231
+ */
232
+ public $ssl_verification = true;
233
+
234
+ /**
235
+ * The proxy to use for connecting.
236
+ */
237
+ public $proxy = null;
238
+
239
+ /**
240
+ * The alternate hostname to use, if any.
241
+ */
242
+ public $hostname = null;
243
+
244
+ /**
245
+ * The state of the capability to override the hostname with <set_hostname()>.
246
+ */
247
+ public $override_hostname = true;
248
+
249
+ /**
250
+ * The alternate port number to use, if any.
251
+ */
252
+ public $port_number = null;
253
+
254
+ /**
255
+ * The alternate resource prefix to use, if any.
256
+ */
257
+ public $resource_prefix = null;
258
+
259
+ /**
260
+ * The state of cache flow usage.
261
+ */
262
+ public $use_cache_flow = false;
263
+
264
+ /**
265
+ * The caching class to use.
266
+ */
267
+ public $cache_class = null;
268
+
269
+ /**
270
+ * The caching location to use.
271
+ */
272
+ public $cache_location = null;
273
+
274
+ /**
275
+ * When the cache should be considered stale.
276
+ */
277
+ public $cache_expires = null;
278
+
279
+ /**
280
+ * The state of cache compression.
281
+ */
282
+ public $cache_compress = null;
283
+
284
+ /**
285
+ * The current instantiated cache object.
286
+ */
287
+ public $cache_object = null;
288
+
289
+ /**
290
+ * The current instantiated batch request object.
291
+ */
292
+ public $batch_object = null;
293
+
294
+ /**
295
+ * The internally instantiated batch request object.
296
+ */
297
+ public $internal_batch_object = null;
298
+
299
+ /**
300
+ * The state of batch flow usage.
301
+ */
302
+ public $use_batch_flow = false;
303
+
304
+ /**
305
+ * The state of the cache deletion setting.
306
+ */
307
+ public $delete_cache = false;
308
+
309
+ /**
310
+ * The state of the debug mode setting.
311
+ */
312
+ public $debug_mode = false;
313
+
314
+ /**
315
+ * The number of times to retry failed requests.
316
+ */
317
+ public $max_retries = 3;
318
+
319
+ /**
320
+ * The user-defined callback function to call when a stream is read from.
321
+ */
322
+ public $registered_streaming_read_callback = null;
323
+
324
+ /**
325
+ * The user-defined callback function to call when a stream is written to.
326
+ */
327
+ public $registered_streaming_write_callback = null;
328
+
329
+ /**
330
+ * The credentials to use for authentication.
331
+ */
332
+ public $credentials = array();
333
+
334
+ /**
335
+ * The authentication class to use.
336
+ */
337
+ public $auth_class = null;
338
+
339
+ /**
340
+ * The operation to execute.
341
+ */
342
+ public $operation = null;
343
+
344
+ /**
345
+ * The payload to send.
346
+ */
347
+ public $payload = array();
348
+
349
+ /**
350
+ * The string prefix to prepend to the operation name.
351
+ */
352
+ public $operation_prefix = '';
353
+
354
+ /**
355
+ * The number of times a request has been retried.
356
+ */
357
+ public $redirects = 0;
358
+
359
+ /**
360
+ * The state of whether the response should be parsed or not.
361
+ */
362
+ public $parse_the_response = true;
363
+
364
+
365
+ /*%******************************************************************************************%*/
366
+ // CONSTRUCTOR
367
+
368
+ /**
369
+ * The constructor. This class should not be instantiated directly. Rather, a service-specific class
370
+ * should be instantiated.
371
+ *
372
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
373
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
374
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
375
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
376
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
377
+ * <li><code>instance_profile_timeout</code> - <code>integer</code> - Optional - When retrieving IAM instance profile credentials, there is a hard connection timeout that defaults to 2 seconds to prevent unnecessary on non-EC2 systems. This setting allows you to change that timeout if needed.</li>
378
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
379
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li>
380
+ * <li><code>use_instance_profile_credentials</code> - <code>boolean</code> - Optional - Forces the use of IAM Instance Profile credentials, even when regular credentials are provided.</li></ul>
381
+ * @return void
382
+ */
383
+ public function __construct(array $options = array())
384
+ {
385
+ // Instantiate the utilities class.
386
+ $this->util = new $this->utilities_class();
387
+
388
+ // Determine the current service.
389
+ $this->service = get_class($this);
390
+
391
+ // Create credentials based on the options
392
+ $runtime_credentials = new CFCredential($options);
393
+ $credentials_provided = false;
394
+
395
+ // Retrieve a credential set from config.inc.php if it exists
396
+ if (isset($options['credentials']))
397
+ {
398
+ // Use a specific credential set and merge with the runtime credentials
399
+ $this->credentials = CFCredentials::get($options['credentials'])
400
+ ->merge($runtime_credentials);
401
+ }
402
+ else
403
+ {
404
+ try
405
+ {
406
+ // Use the default credential set and merge with the runtime credentials
407
+ $this->credentials = CFCredentials::get(CFCredentials::DEFAULT_KEY)
408
+ ->merge($runtime_credentials);
409
+ }
410
+ catch (CFCredentials_Exception $e)
411
+ {
412
+ // Only the runtime credentials were provided
413
+ $this->credentials = $runtime_credentials;
414
+ }
415
+ }
416
+
417
+ // Check if keys were actually provided
418
+ if (isset($this->credentials['key']) && isset($this->credentials['secret']))
419
+ {
420
+ $credentials_provided = true;
421
+ }
422
+
423
+ // Check for an instance profile credentials override
424
+ if (isset($this->credentials['use_instance_profile_credentials']) && $this->credentials['use_instance_profile_credentials'])
425
+ {
426
+ $credentials_provided = false;
427
+ }
428
+
429
+ // Automatically enable whichever caching mechanism is set to default.
430
+ $this->set_cache_config($this->credentials->default_cache_config);
431
+
432
+ // If no credentials were provided, try to get them from the EC2 instance profile
433
+ if (!$credentials_provided)
434
+ {
435
+ // Default caching mechanism is required
436
+ if (!$this->credentials->default_cache_config)
437
+ {
438
+ // @codeCoverageIgnoreStart
439
+ throw new CFCredentials_Exception('No credentials were provided. The SDK attempts to retrieve Instance '
440
+ . 'Profile credentials from the EC2 Instance Metadata Service, but doing this requires the '
441
+ . '"default_cache_config" option to be set in the config.inc.php file or constructor. In order to '
442
+ . 'cache the retrieved credentials.');
443
+ // @codeCoverageIgnoreEnd
444
+ }
445
+
446
+ // Instantiate and invoke the cache for instance profile credentials
447
+ $cache = new $this->cache_class('instance_profile_credentials', $this->cache_location, 0, $this->cache_compress);
448
+ if ($data = $cache->read())
449
+ {
450
+ $cache->expire_in((strtotime($data['expires']) - time()) * 0.85);
451
+ }
452
+ $instance_profile_credentials = $cache->response_manager(array($this, 'cache_instance_profile_credentials'), array($cache, $options));
453
+
454
+ $this->credentials->key = $instance_profile_credentials['key'];
455
+ $this->credentials->secret = $instance_profile_credentials['secret'];
456
+ $this->credentials->token = $instance_profile_credentials['token'];
457
+ }
458
+
459
+ // Set internal credentials after they are resolved
460
+ $this->key = $this->credentials->key;
461
+ $this->secret_key = $this->credentials->secret;
462
+ $this->auth_token = $this->credentials->token;
463
+ }
464
+
465
+ /**
466
+ * Alternate approach to constructing a new instance. Supports chaining.
467
+ *
468
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
469
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
470
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
471
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
472
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
473
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
474
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
475
+ * @return void
476
+ */
477
+ public static function factory(array $options = array())
478
+ {
479
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
480
+ {
481
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::factory().');
482
+ }
483
+
484
+ $self = get_called_class();
485
+ return new $self($options);
486
+ }
487
+
488
+
489
+ /*%******************************************************************************************%*/
490
+ // MAGIC METHODS
491
+
492
+ /**
493
+ * A magic method that allows `camelCase` method names to be translated into `snake_case` names.
494
+ *
495
+ * @param string $name (Required) The name of the method.
496
+ * @param array $arguments (Required) The arguments passed to the method.
497
+ * @return mixed The results of the intended method.
498
+ */
499
+ public function __call($name, $arguments)
500
+ {
501
+ // Convert camelCase method calls to snake_case.
502
+ $method_name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
503
+
504
+ if (method_exists($this, $method_name))
505
+ {
506
+ return call_user_func_array(array($this, $method_name), $arguments);
507
+ }
508
+
509
+ throw new CFRuntime_Exception('The method ' . $name . '() is undefined. Attempted to map to ' . $method_name . '() which is also undefined. Error occurred');
510
+ }
511
+
512
+
513
+ /*%******************************************************************************************%*/
514
+ // SET CUSTOM SETTINGS
515
+
516
+ /**
517
+ * Set the proxy settings to use.
518
+ *
519
+ * @param string $proxy (Required) Accepts proxy credentials in the following format: `proxy://user:pass@hostname:port`
520
+ * @return $this A reference to the current instance.
521
+ */
522
+ public function set_proxy($proxy)
523
+ {
524
+ $this->proxy = $proxy;
525
+ return $this;
526
+ }
527
+
528
+ /**
529
+ * Set the hostname to connect to. This is useful for alternate services that are API-compatible with
530
+ * AWS, but run from a different hostname.
531
+ *
532
+ * @param string $hostname (Required) The alternate hostname to use in place of the default one. Useful for mock or test applications living on different hostnames.
533
+ * @param integer $port_number (Optional) The alternate port number to use in place of the default one. Useful for mock or test applications living on different port numbers.
534
+ * @return $this A reference to the current instance.
535
+ */
536
+ public function set_hostname($hostname, $port_number = null)
537
+ {
538
+ if ($this->override_hostname)
539
+ {
540
+ $this->hostname = $hostname;
541
+
542
+ if ($port_number)
543
+ {
544
+ $this->port_number = $port_number;
545
+ $this->hostname .= ':' . (string) $this->port_number;
546
+ }
547
+ }
548
+
549
+ return $this;
550
+ }
551
+
552
+ /**
553
+ * Set the resource prefix to use. This method is useful for alternate services that are API-compatible
554
+ * with AWS.
555
+ *
556
+ * @param string $prefix (Required) An alternate prefix to prepend to the resource path. Useful for mock or test applications.
557
+ * @return $this A reference to the current instance.
558
+ */
559
+ public function set_resource_prefix($prefix)
560
+ {
561
+ $this->resource_prefix = $prefix;
562
+ return $this;
563
+ }
564
+
565
+ /**
566
+ * Disables any subsequent use of the <set_hostname()> method.
567
+ *
568
+ * @param boolean $override (Optional) Whether or not subsequent calls to <set_hostname()> should be obeyed. A `false` value disables the further effectiveness of <set_hostname()>. Defaults to `true`.
569
+ * @return $this A reference to the current instance.
570
+ */
571
+ public function allow_hostname_override($override = true)
572
+ {
573
+ $this->override_hostname = $override;
574
+ return $this;
575
+ }
576
+
577
+ /**
578
+ * Disables SSL/HTTPS connections for hosts that don't support them. Some services, however, still
579
+ * require SSL support.
580
+ *
581
+ * This method will throw a user warning when invoked, which can be hidden by changing your
582
+ * <php:error_reporting()> settings.
583
+ *
584
+ * @return $this A reference to the current instance.
585
+ */
586
+ public function disable_ssl()
587
+ {
588
+ trigger_error('Disabling SSL connections is potentially unsafe and highly discouraged.', E_USER_WARNING);
589
+ $this->use_ssl = false;
590
+ return $this;
591
+ }
592
+
593
+ /**
594
+ * Disables the verification of the SSL Certificate Authority. Doing so can enable an attacker to carry
595
+ * out a man-in-the-middle attack.
596
+ *
597
+ * https://secure.wikimedia.org/wikipedia/en/wiki/Man-in-the-middle_attack
598
+ *
599
+ * This method will throw a user warning when invoked, which can be hidden by changing your
600
+ * <php:error_reporting()> settings.
601
+ *
602
+ * @return $this A reference to the current instance.
603
+ */
604
+ public function disable_ssl_verification($ssl_verification = false)
605
+ {
606
+ trigger_error('Disabling the verification of SSL certificates can lead to man-in-the-middle attacks. It is potentially unsafe and highly discouraged.', E_USER_WARNING);
607
+ $this->ssl_verification = $ssl_verification;
608
+ return $this;
609
+ }
610
+
611
+ /**
612
+ * Enables HTTP request/response header logging to `STDERR`.
613
+ *
614
+ * @param boolean $enabled (Optional) Whether or not to enable debug mode. Defaults to `true`.
615
+ * @return $this A reference to the current instance.
616
+ */
617
+ public function enable_debug_mode($enabled = true)
618
+ {
619
+ $this->debug_mode = $enabled;
620
+ return $this;
621
+ }
622
+
623
+ /**
624
+ * Sets the maximum number of times to retry failed requests.
625
+ *
626
+ * @param integer $retries (Optional) The maximum number of times to retry failed requests. Defaults to `3`.
627
+ * @return $this A reference to the current instance.
628
+ */
629
+ public function set_max_retries($retries = 3)
630
+ {
631
+ $this->max_retries = $retries;
632
+ return $this;
633
+ }
634
+
635
+ /**
636
+ * Set the caching configuration to use for response caching.
637
+ *
638
+ * @param string $location (Required) <p>The location to store the cache object in. This may vary by cache method.</p><ul><li>File - The local file system paths such as <code>./cache</code> (relative) or <code>/tmp/cache/</code> (absolute). The location must be server-writable.</li><li>APC - Pass in <code>apc</code> to use this lightweight cache. You must have the <a href="http://php.net/apc">APC extension</a> installed.</li><li>XCache - Pass in <code>xcache</code> to use this lightweight cache. You must have the <a href="http://xcache.lighttpd.net">XCache</a> extension installed.</li><li>Memcached - Pass in an indexed array of associative arrays. Each associative array should have a <code>host</code> and a <code>port</code> value representing a <a href="http://php.net/memcached">Memcached</a> server to connect to.</li><li>PDO - A URL-style string (e.g. <code>pdo.mysql://user:pass@localhost/cache</code>) or a standard DSN-style string (e.g. <code>pdo.sqlite:/sqlite/cache.db</code>). MUST be prefixed with <code>pdo.</code>. See <code>CachePDO</code> and <a href="http://php.net/pdo">PDO</a> for more details.</li></ul>
639
+ * @param boolean $gzip (Optional) Whether or not data should be gzipped before being stored. A value of `true` will compress the contents before caching them. A value of `false` will leave the contents uncompressed. Defaults to `true`.
640
+ * @return $this A reference to the current instance.
641
+ */
642
+ public function set_cache_config($location, $gzip = true)
643
+ {
644
+ // If location is empty, don't do anything.
645
+ if (empty($location))
646
+ {
647
+ return $this;
648
+ }
649
+
650
+ // If we have an array, we're probably passing in Memcached servers and ports.
651
+ if (is_array($location))
652
+ {
653
+ $this->cache_class = 'CacheMC';
654
+ }
655
+ else
656
+ {
657
+ // I would expect locations like `/tmp/cache`, `pdo.mysql://user:pass@hostname:port`, `pdo.sqlite:memory:`, and `apc`.
658
+ $type = strtolower(substr($location, 0, 3));
659
+ switch ($type)
660
+ {
661
+ case 'apc':
662
+ $this->cache_class = 'CacheAPC';
663
+ break;
664
+
665
+ case 'xca': // First three letters of `xcache`
666
+ $this->cache_class = 'CacheXCache';
667
+ break;
668
+
669
+ case 'pdo':
670
+ $this->cache_class = 'CachePDO';
671
+ $location = substr($location, 4);
672
+ break;
673
+
674
+ default:
675
+ $this->cache_class = 'CacheFile';
676
+ break;
677
+ }
678
+ }
679
+
680
+ // Set the remaining cache information.
681
+ $this->cache_location = $location;
682
+ $this->cache_compress = $gzip;
683
+
684
+ return $this;
685
+ }
686
+
687
+ /**
688
+ * Register a callback function to execute whenever a data stream is read from using
689
+ * <CFRequest::streaming_read_callback()>.
690
+ *
691
+ * The user-defined callback function should accept three arguments:
692
+ *
693
+ * <ul>
694
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
695
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
696
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
697
+ * </ul>
698
+ *
699
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
700
+ * <li>The name of a global function to execute, passed as a string.</li>
701
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
702
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
703
+ * @return $this A reference to the current instance.
704
+ */
705
+ public function register_streaming_read_callback($callback)
706
+ {
707
+ $this->registered_streaming_read_callback = $callback;
708
+ return $this;
709
+ }
710
+
711
+ /**
712
+ * Register a callback function to execute whenever a data stream is written to using
713
+ * <CFRequest::streaming_write_callback()>.
714
+ *
715
+ * The user-defined callback function should accept two arguments:
716
+ *
717
+ * <ul>
718
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
719
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
720
+ * </ul>
721
+ *
722
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
723
+ * <li>The name of a global function to execute, passed as a string.</li>
724
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
725
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
726
+ * @return $this A reference to the current instance.
727
+ */
728
+ public function register_streaming_write_callback($callback)
729
+ {
730
+ $this->registered_streaming_write_callback = $callback;
731
+ return $this;
732
+ }
733
+
734
+ /**
735
+ * Fetches and caches STS credentials. This is meant to be used by the constructor, and is not to be
736
+ * manually invoked.
737
+ *
738
+ * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
739
+ * @param array $options (Required) The options that were passed into the constructor.
740
+ * @return mixed The data to be cached, or NULL.
741
+ */
742
+ public function cache_sts_credentials($cache, $options)
743
+ {
744
+ $token = new AmazonSTS($options);
745
+ $response = $token->get_session_token();
746
+
747
+ if ($response->isOK())
748
+ {
749
+ // Update the expiration
750
+ $expiration_time = strtotime((string) $response->body->GetSessionTokenResult->Credentials->Expiration);
751
+ $expiration_duration = round(($expiration_time - time()) * 0.85);
752
+ $cache->expire_in($expiration_duration);
753
+
754
+ // Return the important data
755
+ $credentials = $response->body->GetSessionTokenResult->Credentials;
756
+
757
+ return array(
758
+ 'key' => (string) $credentials->AccessKeyId,
759
+ 'secret' => (string) $credentials->SecretAccessKey,
760
+ 'token' => (string) $credentials->SessionToken,
761
+ 'expires' => (string) $credentials->Expiration,
762
+ );
763
+ }
764
+
765
+ // @codeCoverageIgnoreStart
766
+ throw new STS_Exception('Temporary credentials from the AWS Security '
767
+ . 'Token Service could not be retrieved using the provided long '
768
+ . 'term credentials. It\'s possible that the provided long term '
769
+ . 'credentials were invalid.');
770
+ // @codeCoverageIgnoreEnd
771
+ }
772
+
773
+ /**
774
+ * Fetches and caches EC2 instance profile credentials. This is meant to be used by the constructor, and is not to
775
+ * be manually invoked.
776
+ *
777
+ * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
778
+ * @param array $options (Required) The options that were passed into the constructor.
779
+ * @return mixed The data to be cached, or NULL.
780
+ */
781
+ public function cache_instance_profile_credentials($cache, $options)
782
+ {
783
+ $instance_profile_url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/';
784
+ $connect_timeout = isset($options['instance_profile_timeout']) ? $options['instance_profile_timeout'] : 2;
785
+
786
+ try
787
+ {
788
+ // Make a call to the EC2 Metadata Service to find the available instance profile
789
+ $request = new RequestCore($instance_profile_url);
790
+ $request->set_curlopts(array(CURLOPT_CONNECTTIMEOUT => $connect_timeout));
791
+ $response = $request->send_request(true);
792
+
793
+ if ($response->isOK())
794
+ {
795
+ // Get the instance profile name
796
+ $profile = (string) $response->body;
797
+
798
+ // Make a call to the EC2 Metadata Service to get the instance profile credentials
799
+ $request = new RequestCore($instance_profile_url . $profile);
800
+ $request->set_curlopts(array(CURLOPT_CONNECTTIMEOUT => $connect_timeout));
801
+ $response = $request->send_request(true);
802
+
803
+ if ($response->isOK())
804
+ {
805
+ // Get the credentials
806
+ $credentials = json_decode($response->body, true);
807
+
808
+ if ($credentials['Code'] === 'Success')
809
+ {
810
+ // Determine the expiration time
811
+ $expiration_time = strtotime((string) $credentials['Expiration']);
812
+ $expiration_duration = round(($expiration_time - time()) * 0.85);
813
+ $cache->expire_in($expiration_duration);
814
+
815
+ // Return the credential information
816
+ return array(
817
+ 'key' => $credentials['AccessKeyId'],
818
+ 'secret' => $credentials['SecretAccessKey'],
819
+ 'token' => $credentials['Token'],
820
+ 'expires' => $credentials['Expiration'],
821
+ );
822
+ }
823
+ }
824
+ }
825
+ }
826
+ catch (cURL_Exception $e)
827
+ {
828
+ // The EC2 Metadata Service does not exist or had timed out.
829
+ // An exception will be thrown on the next line.
830
+ }
831
+
832
+ // @codeCoverageIgnoreStart
833
+ throw new CFCredentials_Exception('No credentials were provided. The SDK attempted to retrieve Instance '
834
+ . 'Profile credentials from the EC2 Instance Metadata Service, but failed to do so. Instance profile '
835
+ . 'credentials are only accessible on EC2 instances configured with a specific IAM role.');
836
+ // @codeCoverageIgnoreEnd
837
+ }
838
+
839
+
840
+ /*%******************************************************************************************%*/
841
+ // SET CUSTOM CLASSES
842
+
843
+ /**
844
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
845
+ * with new functionality.
846
+ *
847
+ * The replacement class must extend from <CFUtilities>.
848
+ *
849
+ * @param string $class (Optional) The name of the new class to use for this functionality.
850
+ * @return $this A reference to the current instance.
851
+ */
852
+ public function set_utilities_class($class = 'CFUtilities')
853
+ {
854
+ $this->utilities_class = $class;
855
+ $this->util = new $this->utilities_class();
856
+ return $this;
857
+ }
858
+
859
+ /**
860
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
861
+ * with new functionality.
862
+ *
863
+ * The replacement class must extend from <CFRequest>.
864
+ *
865
+ * @param string $class (Optional) The name of the new class to use for this functionality.
866
+ * @param $this A reference to the current instance.
867
+ */
868
+ public function set_request_class($class = 'CFRequest')
869
+ {
870
+ $this->request_class = $class;
871
+ return $this;
872
+ }
873
+
874
+ /**
875
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
876
+ * with new functionality.
877
+ *
878
+ * The replacement class must extend from <CFResponse>.
879
+ *
880
+ * @param string $class (Optional) The name of the new class to use for this functionality.
881
+ * @return $this A reference to the current instance.
882
+ */
883
+ public function set_response_class($class = 'CFResponse')
884
+ {
885
+ $this->response_class = $class;
886
+ return $this;
887
+ }
888
+
889
+ /**
890
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
891
+ * with new functionality.
892
+ *
893
+ * The replacement class must extend from <CFSimpleXML>.
894
+ *
895
+ * @param string $class (Optional) The name of the new class to use for this functionality.
896
+ * @return $this A reference to the current instance.
897
+ */
898
+ public function set_parser_class($class = 'CFSimpleXML')
899
+ {
900
+ $this->parser_class = $class;
901
+ return $this;
902
+ }
903
+
904
+ /**
905
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
906
+ * with new functionality.
907
+ *
908
+ * The replacement class must extend from <CFBatchRequest>.
909
+ *
910
+ * @param string $class (Optional) The name of the new class to use for this functionality.
911
+ * @return $this A reference to the current instance.
912
+ */
913
+ public function set_batch_class($class = 'CFBatchRequest')
914
+ {
915
+ $this->batch_class = $class;
916
+ return $this;
917
+ }
918
+
919
+
920
+ /*%******************************************************************************************%*/
921
+ // AUTHENTICATION
922
+
923
+ /**
924
+ * Default, shared method for authenticating a connection to AWS.
925
+ *
926
+ * @param string $operation (Required) Indicates the operation to perform.
927
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
928
+ * @return CFResponse Object containing a parsed HTTP response.
929
+ */
930
+ public function authenticate($operation, $payload)
931
+ {
932
+ $original_payload = $payload;
933
+ $method_arguments = func_get_args();
934
+ $curlopts = array();
935
+ $return_curl_handle = false;
936
+
937
+ if (substr($operation, 0, strlen($this->operation_prefix)) !== $this->operation_prefix)
938
+ {
939
+ $operation = $this->operation_prefix . $operation;
940
+ }
941
+
942
+ // Extract the custom CURLOPT settings from the payload
943
+ if (is_array($payload) && isset($payload['curlopts']))
944
+ {
945
+ $curlopts = $payload['curlopts'];
946
+ unset($payload['curlopts']);
947
+ }
948
+
949
+ // Determine whether the response or curl handle should be returned
950
+ if (is_array($payload) && isset($payload['returnCurlHandle']))
951
+ {
952
+ $return_curl_handle = isset($payload['returnCurlHandle']) ? $payload['returnCurlHandle'] : false;
953
+ unset($payload['returnCurlHandle']);
954
+ }
955
+
956
+ // Use the caching flow to determine if we need to do a round-trip to the server.
957
+ if ($this->use_cache_flow)
958
+ {
959
+ // Generate an identifier specific to this particular set of arguments.
960
+ $cache_id = $this->key . '_' . get_class($this) . '_' . $operation . '_' . sha1(serialize($method_arguments));
961
+
962
+ // Instantiate the appropriate caching object.
963
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
964
+
965
+ if ($this->delete_cache)
966
+ {
967
+ $this->use_cache_flow = false;
968
+ $this->delete_cache = false;
969
+ return $this->cache_object->delete();
970
+ }
971
+
972
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
973
+ $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
974
+
975
+ // Parse the XML body
976
+ $data = $this->parse_callback($data);
977
+
978
+ // End!
979
+ return $data;
980
+ }
981
+
982
+ /*%******************************************************************************************%*/
983
+
984
+ // Signer
985
+ $signer = new $this->auth_class($this->hostname, $operation, $payload, $this->credentials);
986
+ $signer->key = $this->key;
987
+ $signer->secret_key = $this->secret_key;
988
+ $signer->auth_token = $this->auth_token;
989
+ $signer->api_version = $this->api_version;
990
+ $signer->utilities_class = $this->utilities_class;
991
+ $signer->request_class = $this->request_class;
992
+ $signer->response_class = $this->response_class;
993
+ $signer->use_ssl = $this->use_ssl;
994
+ $signer->proxy = $this->proxy;
995
+ $signer->util = $this->util;
996
+ $signer->registered_streaming_read_callback = $this->registered_streaming_read_callback;
997
+ $signer->registered_streaming_write_callback = $this->registered_streaming_write_callback;
998
+ $request = $signer->authenticate();
999
+
1000
+ // Update RequestCore settings
1001
+ $request->request_class = $this->request_class;
1002
+ $request->response_class = $this->response_class;
1003
+ $request->ssl_verification = $this->ssl_verification;
1004
+
1005
+ /*%******************************************************************************************%*/
1006
+
1007
+ // Debug mode
1008
+ if ($this->debug_mode)
1009
+ {
1010
+ $request->debug_mode = $this->debug_mode;
1011
+ }
1012
+
1013
+ // Set custom CURLOPT settings
1014
+ if (count($curlopts))
1015
+ {
1016
+ $request->set_curlopts($curlopts);
1017
+ }
1018
+
1019
+ // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
1020
+ if ($this->use_batch_flow)
1021
+ {
1022
+ $handle = $request->prep_request();
1023
+ $this->batch_object->add($handle);
1024
+ $this->use_batch_flow = false;
1025
+
1026
+ return $handle;
1027
+ }
1028
+ elseif ($return_curl_handle)
1029
+ {
1030
+ return $request->prep_request();
1031
+ }
1032
+
1033
+ // Send!
1034
+ $request->send_request();
1035
+
1036
+ // Prepare the response.
1037
+ $headers = $request->get_response_header();
1038
+ $headers['x-aws-stringtosign'] = $signer->string_to_sign;
1039
+
1040
+ if (isset($signer->canonical_request))
1041
+ {
1042
+ $headers['x-aws-canonicalrequest'] = $signer->canonical_request;
1043
+ }
1044
+
1045
+ $headers['x-aws-request-headers'] = $request->request_headers;
1046
+ $headers['x-aws-body'] = $signer->querystring;
1047
+
1048
+ $data = new $this->response_class($headers, ($this->parse_the_response === true) ? $this->parse_callback($request->get_response_body()) : $request->get_response_body(), $request->get_response_code());
1049
+
1050
+ // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
1051
+ if (
1052
+ (integer) $request->get_response_code() === 500 || // Internal Error (presumably transient)
1053
+ (integer) $request->get_response_code() === 503) // Service Unavailable (presumably transient)
1054
+ {
1055
+ if ($this->redirects <= $this->max_retries)
1056
+ {
1057
+ // Exponential backoff
1058
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
1059
+ usleep($delay);
1060
+ $this->redirects++;
1061
+ $data = $this->authenticate($operation, $original_payload);
1062
+ }
1063
+ }
1064
+
1065
+ // DynamoDB has custom logic
1066
+ elseif (
1067
+ (integer) $request->get_response_code() === 400 &&
1068
+ stripos((string) $request->get_response_body(), 'com.amazonaws.dynamodb.') !== false && (
1069
+ stripos((string) $request->get_response_body(), 'ProvisionedThroughputExceededException') !== false
1070
+ )
1071
+ )
1072
+ {
1073
+ if ($this->redirects === 0)
1074
+ {
1075
+ $this->redirects++;
1076
+ $data = $this->authenticate($operation, $original_payload);
1077
+ }
1078
+ elseif ($this->redirects <= max($this->max_retries, 10))
1079
+ {
1080
+ // Exponential backoff
1081
+ $delay = (integer) (pow(2, ($this->redirects - 1)) * 50000);
1082
+ usleep($delay);
1083
+ $this->redirects++;
1084
+ $data = $this->authenticate($operation, $original_payload);
1085
+ }
1086
+ }
1087
+
1088
+ $this->redirects = 0;
1089
+ return $data;
1090
+ }
1091
+
1092
+
1093
+ /*%******************************************************************************************%*/
1094
+ // BATCH REQUEST LAYER
1095
+
1096
+ /**
1097
+ * Specifies that the intended request should be queued for a later batch request.
1098
+ *
1099
+ * @param CFBatchRequest $queue (Optional) The <CFBatchRequest> instance to use for managing batch requests. If not available, it generates a new instance of <CFBatchRequest>.
1100
+ * @return $this A reference to the current instance.
1101
+ */
1102
+ public function batch(CFBatchRequest &$queue = null)
1103
+ {
1104
+ if ($queue)
1105
+ {
1106
+ $this->batch_object = $queue;
1107
+ }
1108
+ elseif ($this->internal_batch_object)
1109
+ {
1110
+ $this->batch_object = &$this->internal_batch_object;
1111
+ }
1112
+ else
1113
+ {
1114
+ $this->internal_batch_object = new $this->batch_class();
1115
+ $this->batch_object = &$this->internal_batch_object;
1116
+ }
1117
+
1118
+ $this->use_batch_flow = true;
1119
+
1120
+ return $this;
1121
+ }
1122
+
1123
+ /**
1124
+ * Executes the batch request queue by sending all queued requests.
1125
+ *
1126
+ * @param boolean $clear_after_send (Optional) Whether or not to clear the batch queue after sending a request. Defaults to `true`. Set this to `false` if you are caching batch responses and want to retrieve results later.
1127
+ * @return array An array of <CFResponse> objects.
1128
+ */
1129
+ public function send($clear_after_send = true)
1130
+ {
1131
+ if ($this->use_batch_flow)
1132
+ {
1133
+ // When we send the request, disable batch flow.
1134
+ $this->use_batch_flow = false;
1135
+
1136
+ // If we're not caching, simply send the request.
1137
+ if (!$this->use_cache_flow)
1138
+ {
1139
+ $response = $this->batch_object->send();
1140
+ $parsed_data = array_map(array($this, 'parse_callback'), $response);
1141
+ $parsed_data = new CFArray($parsed_data);
1142
+
1143
+ // Clear the queue
1144
+ if ($clear_after_send)
1145
+ {
1146
+ $this->batch_object->queue = array();
1147
+ }
1148
+
1149
+ return $parsed_data;
1150
+ }
1151
+
1152
+ // Generate an identifier specific to this particular set of arguments.
1153
+ $cache_id = $this->key . '_' . get_class($this) . '_' . sha1(serialize($this->batch_object));
1154
+
1155
+ // Instantiate the appropriate caching object.
1156
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
1157
+
1158
+ if ($this->delete_cache)
1159
+ {
1160
+ $this->use_cache_flow = false;
1161
+ $this->delete_cache = false;
1162
+ return $this->cache_object->delete();
1163
+ }
1164
+
1165
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
1166
+ $data_set = $this->cache_object->response_manager(array($this, 'cache_callback_batch'), array($this->batch_object));
1167
+ $parsed_data = array_map(array($this, 'parse_callback'), $data_set);
1168
+ $parsed_data = new CFArray($parsed_data);
1169
+
1170
+ // Clear the queue
1171
+ if ($clear_after_send)
1172
+ {
1173
+ $this->batch_object->queue = array();
1174
+ }
1175
+
1176
+ // End!
1177
+ return $parsed_data;
1178
+ }
1179
+
1180
+ // Load the class
1181
+ $null = new CFBatchRequest();
1182
+ unset($null);
1183
+
1184
+ throw new CFBatchRequest_Exception('You must use $object->batch()->send()');
1185
+ }
1186
+
1187
+ /**
1188
+ * Parses a response body into a PHP object if appropriate.
1189
+ *
1190
+ * @param CFResponse|string $response (Required) The <CFResponse> object to parse, or an XML string that would otherwise be a response body.
1191
+ * @param string $content_type (Optional) The content-type to use when determining how to parse the content.
1192
+ * @return CFResponse|string A parsed <CFResponse> object, or parsed XML.
1193
+ */
1194
+ public function parse_callback($response, $headers = null)
1195
+ {
1196
+ // Bail out
1197
+ if (!$this->parse_the_response) return $response;
1198
+
1199
+ // Shorten this so we have a (mostly) single code path
1200
+ if (isset($response->body))
1201
+ {
1202
+ if (is_string($response->body))
1203
+ {
1204
+ $body = $response->body;
1205
+ }
1206
+ else
1207
+ {
1208
+ return $response;
1209
+ }
1210
+ }
1211
+ elseif (is_string($response))
1212
+ {
1213
+ $body = $response;
1214
+ }
1215
+ else
1216
+ {
1217
+ return $response;
1218
+ }
1219
+
1220
+ // Decompress gzipped content
1221
+ if (isset($headers['content-encoding']))
1222
+ {
1223
+ switch (strtolower(trim($headers['content-encoding'], "\x09\x0A\x0D\x20")))
1224
+ {
1225
+ case 'gzip':
1226
+ case 'x-gzip':
1227
+ $decoder = new CFGzipDecode($body);
1228
+ if ($decoder->parse())
1229
+ {
1230
+ $body = $decoder->data;
1231
+ }
1232
+ break;
1233
+
1234
+ case 'deflate':
1235
+ if (($uncompressed = gzuncompress($body)) !== false)
1236
+ {
1237
+ $body = $uncompressed;
1238
+ }
1239
+ elseif (($uncompressed = gzinflate($body)) !== false)
1240
+ {
1241
+ $body = $uncompressed;
1242
+ }
1243
+ break;
1244
+ }
1245
+ }
1246
+
1247
+ // Look for XML cues
1248
+ if (
1249
+ (isset($headers['content-type']) && ($headers['content-type'] === 'text/xml' || $headers['content-type'] === 'application/xml')) || // We know it's XML
1250
+ (!isset($headers['content-type']) && (stripos($body, '<?xml') === 0 || strpos($body, '<Error>') === 0) || preg_match('/^<(\w*) xmlns="http(s?):\/\/(\w*).amazon(aws)?.com/im', $body)) // Sniff for XML
1251
+ )
1252
+ {
1253
+ // Strip the default XML namespace to simplify XPath expressions
1254
+ $body = str_replace("xmlns=", "ns=", $body);
1255
+
1256
+ try {
1257
+ // Parse the XML body
1258
+ $body = new $this->parser_class($body);
1259
+ }
1260
+ catch (Exception $e)
1261
+ {
1262
+ throw new Parser_Exception($e->getMessage());
1263
+ }
1264
+ }
1265
+ // Look for JSON cues
1266
+ elseif (
1267
+ (isset($headers['content-type']) && ($headers['content-type'] === 'application/json') || $headers['content-type'] === 'application/x-amz-json-1.0') || // We know it's JSON
1268
+ (!isset($headers['content-type']) && $this->util->is_json($body)) // Sniff for JSON
1269
+ )
1270
+ {
1271
+ // Normalize JSON to a CFSimpleXML object
1272
+ $body = CFJSON::to_xml($body, $this->parser_class);
1273
+ }
1274
+
1275
+ // Put the parsed data back where it goes
1276
+ if (isset($response->body))
1277
+ {
1278
+ $response->body = $body;
1279
+ }
1280
+ else
1281
+ {
1282
+ $response = $body;
1283
+ }
1284
+
1285
+ return $response;
1286
+ }
1287
+
1288
+
1289
+ /*%******************************************************************************************%*/
1290
+ // CACHING LAYER
1291
+
1292
+ /**
1293
+ * Specifies that the resulting <CFResponse> object should be cached according to the settings from
1294
+ * <set_cache_config()>.
1295
+ *
1296
+ * @param string|integer $expires (Required) The time the cache is to expire. Accepts a number of seconds as an integer, or an amount of time, as a string, that is understood by <php:strtotime()> (e.g. "1 hour").
1297
+ * @param $this A reference to the current instance.
1298
+ * @return $this
1299
+ */
1300
+ public function cache($expires)
1301
+ {
1302
+ // Die if they haven't used set_cache_config().
1303
+ if (!$this->cache_class)
1304
+ {
1305
+ throw new CFRuntime_Exception('Must call set_cache_config() before using cache()');
1306
+ }
1307
+
1308
+ if (is_string($expires))
1309
+ {
1310
+ $expires = strtotime($expires);
1311
+ $this->cache_expires = $expires - time();
1312
+ }
1313
+ elseif (is_int($expires))
1314
+ {
1315
+ $this->cache_expires = $expires;
1316
+ }
1317
+
1318
+ $this->use_cache_flow = true;
1319
+
1320
+ return $this;
1321
+ }
1322
+
1323
+ /**
1324
+ * The callback function that is executed when the cache doesn't exist or has expired. The response of
1325
+ * this method is cached. Accepts identical parameters as the <authenticate()> method. Never call this
1326
+ * method directly -- it is used internally by the caching system.
1327
+ *
1328
+ * @param string $operation (Required) Indicates the operation to perform.
1329
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
1330
+ * @return CFResponse A parsed HTTP response.
1331
+ */
1332
+ public function cache_callback($operation, $payload)
1333
+ {
1334
+ // Disable the cache flow since it's already been handled.
1335
+ $this->use_cache_flow = false;
1336
+
1337
+ // Make the request
1338
+ $response = $this->authenticate($operation, $payload);
1339
+
1340
+ // If this is an XML document, convert it back to a string.
1341
+ if (isset($response->body) && ($response->body instanceof SimpleXMLElement))
1342
+ {
1343
+ $response->body = $response->body->asXML();
1344
+ }
1345
+
1346
+ return $response;
1347
+ }
1348
+
1349
+ /**
1350
+ * Used for caching the results of a batch request. Never call this method directly; it is used
1351
+ * internally by the caching system.
1352
+ *
1353
+ * @param CFBatchRequest $batch (Required) The batch request object to send.
1354
+ * @return CFResponse A parsed HTTP response.
1355
+ */
1356
+ public function cache_callback_batch(CFBatchRequest $batch)
1357
+ {
1358
+ return $batch->send();
1359
+ }
1360
+
1361
+ /**
1362
+ * Deletes a cached <CFResponse> object using the specified cache storage type.
1363
+ *
1364
+ * @return boolean A value of `true` if cached object exists and is successfully deleted, otherwise `false`.
1365
+ */
1366
+ public function delete_cache()
1367
+ {
1368
+ $this->use_cache_flow = true;
1369
+ $this->delete_cache = true;
1370
+
1371
+ return $this;
1372
+ }
1373
+ }
1374
+
1375
+
1376
+ /**
1377
+ * Contains the functionality for auto-loading service classes.
1378
+ */
1379
+ class CFLoader
1380
+ {
1381
+ /*%******************************************************************************************%*/
1382
+ // AUTO-LOADER
1383
+
1384
+ /**
1385
+ * Automatically load classes that aren't included.
1386
+ *
1387
+ * @param string $class (Required) The classname to load.
1388
+ * @return boolean Whether or not the file was successfully loaded.
1389
+ */
1390
+ public static function autoloader($class)
1391
+ {
1392
+ $path = dirname(__FILE__) . DIRECTORY_SEPARATOR;
1393
+
1394
+ // Amazon SDK classes
1395
+ if (strstr($class, 'Amazon'))
1396
+ {
1397
+ if (file_exists($require_this = $path . 'services' . DIRECTORY_SEPARATOR . str_ireplace('Amazon', '', strtolower($class)) . '.class.php'))
1398
+ {
1399
+ require_once $require_this;
1400
+ return true;
1401
+ }
1402
+
1403
+ return false;
1404
+ }
1405
+
1406
+ // Utility classes
1407
+ elseif (strstr($class, 'CF'))
1408
+ {
1409
+ if (file_exists($require_this = $path . 'utilities' . DIRECTORY_SEPARATOR . str_ireplace('CF', '', strtolower($class)) . '.class.php'))
1410
+ {
1411
+ require_once $require_this;
1412
+ return true;
1413
+ }
1414
+
1415
+ return false;
1416
+ }
1417
+
1418
+ // Load CacheCore
1419
+ elseif (strstr($class, 'Cache'))
1420
+ {
1421
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'cachecore' . DIRECTORY_SEPARATOR . strtolower($class) . '.class.php'))
1422
+ {
1423
+ require_once $require_this;
1424
+ return true;
1425
+ }
1426
+
1427
+ return false;
1428
+ }
1429
+
1430
+ // Load RequestCore
1431
+ elseif (strstr($class, 'RequestCore') || strstr($class, 'ResponseCore'))
1432
+ {
1433
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'requestcore' . DIRECTORY_SEPARATOR . 'requestcore.class.php'))
1434
+ {
1435
+ require_once $require_this;
1436
+ return true;
1437
+ }
1438
+
1439
+ return false;
1440
+ }
1441
+
1442
+ // Load Transmogrifier
1443
+ elseif (strstr($class, 'Transmogrifier'))
1444
+ {
1445
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'dom' . DIRECTORY_SEPARATOR . 'Transmogrifier.php'))
1446
+ {
1447
+ require_once $require_this;
1448
+ return true;
1449
+ }
1450
+
1451
+ return false;
1452
+ }
1453
+
1454
+ // Load Authentication Signers
1455
+ elseif (strstr($class, 'Auth'))
1456
+ {
1457
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . str_replace('auth', 'signature_', strtolower($class)) . '.class.php'))
1458
+ {
1459
+ require_once $require_this;
1460
+ return true;
1461
+ }
1462
+
1463
+ return false;
1464
+ }
1465
+
1466
+ // Load Signer interface
1467
+ elseif ($class === 'Signer')
1468
+ {
1469
+ if (!interface_exists('Signable', false) &&
1470
+ file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signable.interface.php'))
1471
+ {
1472
+ require_once $require_this;
1473
+ }
1474
+
1475
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signer.abstract.php'))
1476
+ {
1477
+ require_once $require_this;
1478
+ return true;
1479
+ }
1480
+
1481
+ return false;
1482
+ }
1483
+
1484
+ // Load Symfony YAML classes
1485
+ elseif (strstr($class, 'sfYaml'))
1486
+ {
1487
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'yaml' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sfYaml.php'))
1488
+ {
1489
+ require_once $require_this;
1490
+ return true;
1491
+ }
1492
+
1493
+ return false;
1494
+ }
1495
+
1496
+ return false;
1497
+ }
1498
+ }
1499
+
1500
+ // Register the autoloader.
1501
+ spl_autoload_register(array('CFLoader', 'autoloader'));
1502
+
1503
+
1504
+ /*%******************************************************************************************%*/
1505
+ // CONFIGURATION
1506
+
1507
+ // Look for include file in the same directory (e.g. `./config.inc.php`).
1508
+ if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php'))
1509
+ {
1510
+ include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php';
1511
+ }
1512
+ // Fallback to `~/.aws/sdk/config.inc.php`
1513
+ else
1514
+ {
1515
+ if (!isset($_ENV['HOME']) && isset($_SERVER['HOME']))
1516
+ {
1517
+ $_ENV['HOME'] = $_SERVER['HOME'];
1518
+ }
1519
+ elseif (!isset($_ENV['HOME']) && !isset($_SERVER['HOME']))
1520
+ {
1521
+ $os = strtolower(PHP_OS);
1522
+ if (in_array($os, array('windows', 'winnt', 'win32')))
1523
+ {
1524
+ $_ENV['HOME'] = false;
1525
+ }
1526
+ else
1527
+ {
1528
+ $_ENV['HOME'] = `cd ~ && pwd`;
1529
+ }
1530
+
1531
+ if (!$_ENV['HOME'])
1532
+ {
1533
+ switch ($os)
1534
+ {
1535
+ case 'darwin':
1536
+ $_ENV['HOME'] = '/Users/' . get_current_user();
1537
+ break;
1538
+
1539
+ case 'windows':
1540
+ case 'winnt':
1541
+ case 'win32':
1542
+ $_ENV['HOME'] = 'c:' . DIRECTORY_SEPARATOR . 'Documents and Settings' . DIRECTORY_SEPARATOR . get_current_user();
1543
+ break;
1544
+
1545
+ default:
1546
+ $_ENV['HOME'] = '/home/' . get_current_user();
1547
+ break;
1548
+ }
1549
+ }
1550
+ }
1551
+
1552
+ if (getenv('HOME') && @file_exists(getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php'))
1553
+ {
1554
+ include_once getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php';
1555
+ }
1556
+ }
readme.txt CHANGED
@@ -48,8 +48,11 @@ Credits: [Vladimir Prelovac](http://prelovac.com/vladimir) for his worker plugin
48
 
49
  == Changelog ==
50
 
 
 
 
51
  = 1.2.5 =
52
- * Improvement: Compactible for WP updates 3.7+
53
 
54
 
55
  = 1.2.4 =
48
 
49
  == Changelog ==
50
 
51
+ = 1.2.6 =
52
+ * Fix: Bug fixes
53
+
54
  = 1.2.5 =
55
+ * Improvement: Compatible with WP updates 3.7+
56
 
57
 
58
  = 1.2.4 =