Version Description
- Premium addons compatibility
- Clearing cache and sending WP data
- Bugs fixed
Download this release
Release Info
Developer | infinitewp |
Plugin | InfiniteWP Client |
Version | 1.0.4 |
Comparing to | |
See all releases |
Code changes from version 1.0.3 to 1.0.4
- addons/backup_repository/backup_repository.class.php +453 -0
- backup.class.php +661 -9
- core.class.php +16 -1
- helper.class.php +4 -6
- init.php +53 -3
- installer.class.php +69 -13
- lib/dropbox.oauth.php +1133 -0
- lib/dropbox.php +144 -0
- lib/s3.php +1966 -0
- readme.txt +10 -2
- stats.class.php +19 -7
addons/backup_repository/backup_repository.class.php
ADDED
@@ -0,0 +1,453 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class IWP_MMB_Backup_Repository extends IWP_MMB_Backup
|
3 |
+
{
|
4 |
+
/*var $site_name;
|
5 |
+
var $statuses;
|
6 |
+
var $tasks;
|
7 |
+
var $s3;
|
8 |
+
var $ftp;
|
9 |
+
var $dropbox;
|
10 |
+
|
11 |
+
function __construct()
|
12 |
+
{
|
13 |
+
parent::__construct();
|
14 |
+
$this->site_name = str_replace(array(
|
15 |
+
"_",
|
16 |
+
"/"
|
17 |
+
), array(
|
18 |
+
"",
|
19 |
+
"-"
|
20 |
+
), rtrim($this->remove_http(get_bloginfo('url')), "/"));
|
21 |
+
$this->statuses = array(
|
22 |
+
'db_dump' => 1,
|
23 |
+
'db_zip' => 2,
|
24 |
+
'files_zip' => 3,
|
25 |
+
's3' => 4,
|
26 |
+
'dropbox' => 5,
|
27 |
+
'ftp' => 6,
|
28 |
+
'email' => 7,
|
29 |
+
'finished' => 100
|
30 |
+
);
|
31 |
+
|
32 |
+
$this->tasks = get_option('iwp_client_backup_tasks');
|
33 |
+
}*/
|
34 |
+
|
35 |
+
function backup_repository($args){
|
36 |
+
|
37 |
+
|
38 |
+
if (!empty($args))
|
39 |
+
extract($args);
|
40 |
+
|
41 |
+
$tasks = $this->tasks;
|
42 |
+
$task = $tasks['Backup Now'];
|
43 |
+
|
44 |
+
@ini_set('memory_limit', '256M');
|
45 |
+
@set_time_limit(1200);
|
46 |
+
|
47 |
+
if (!empty($task)) {
|
48 |
+
extract($task['task_args']);
|
49 |
+
}
|
50 |
+
|
51 |
+
$results = $task['task_results'];
|
52 |
+
|
53 |
+
if (is_array($results) && count($results)) {
|
54 |
+
$backup_file = $results[count($results) - 1]['server']['file_path'];
|
55 |
+
}
|
56 |
+
|
57 |
+
|
58 |
+
if ($backup_file && file_exists($backup_file)) {
|
59 |
+
//FTP, Amazon S3 or Dropbox
|
60 |
+
if (isset($account_info['iwp_ftp']) && !empty($account_info)) {
|
61 |
+
$account_info['iwp_ftp']['backup_file'] = $backup_file;
|
62 |
+
$return = $this->ftp_backup($account_info['iwp_ftp']);
|
63 |
+
}
|
64 |
+
|
65 |
+
if (isset($account_info['iwp_amazon_s3']) && !empty($account_info['iwp_amazon_s3'])) {
|
66 |
+
$account_info['iwp_amazon_s3']['backup_file'] = $backup_file;
|
67 |
+
$return = $this->amazons3_backup($account_info['iwp_amazon_s3']);
|
68 |
+
}
|
69 |
+
|
70 |
+
if (isset($account_info['iwp_dropbox']) && !empty($account_info['iwp_dropbox'])) {
|
71 |
+
$account_info['iwp_dropbox']['backup_file'] = $backup_file;
|
72 |
+
$return = $this->dropbox_backup($account_info['iwp_dropbox']);
|
73 |
+
}
|
74 |
+
|
75 |
+
if (isset($account_info['iwp_email']) && !empty($account_info['iwp_email'])) {
|
76 |
+
$account_info['iwp_email']['file_path'] = $backup_file;
|
77 |
+
$account_info['iwp_email']['task_name'] = 'Backup Now';
|
78 |
+
$return = $this->email_backup($account_info['iwp_email']);
|
79 |
+
}
|
80 |
+
|
81 |
+
|
82 |
+
if ($return == true && $del_host_file) {
|
83 |
+
@unlink($backup_file);
|
84 |
+
unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
|
85 |
+
$this->update_tasks($tasks);
|
86 |
+
//update_option('iwp_client_backup_tasks', $tasks);
|
87 |
+
}
|
88 |
+
|
89 |
+
} else {
|
90 |
+
$return = array(
|
91 |
+
'error' => 'Backup file not found on your server. Please try again.'
|
92 |
+
);
|
93 |
+
}
|
94 |
+
|
95 |
+
return $return;
|
96 |
+
|
97 |
+
}
|
98 |
+
/*
|
99 |
+
function ftp_backup($args)
|
100 |
+
{
|
101 |
+
extract($args);
|
102 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
|
103 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
104 |
+
if ($ftp_ssl) {
|
105 |
+
if (function_exists('ftp_ssl_connect')) {
|
106 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
107 |
+
} else {
|
108 |
+
return array(
|
109 |
+
'error' => 'Your server doesn\'t support SFTP',
|
110 |
+
'partial' => 1
|
111 |
+
);
|
112 |
+
}
|
113 |
+
} else {
|
114 |
+
if (function_exists('ftp_connect')) {
|
115 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
116 |
+
if ($conn_id === false) {
|
117 |
+
return array(
|
118 |
+
'error' => 'Failed to connect to ' . $ftp_hostname,
|
119 |
+
'partial' => 1
|
120 |
+
);
|
121 |
+
}
|
122 |
+
} else {
|
123 |
+
return array(
|
124 |
+
'error' => 'Your server doesn\'t support FTP',
|
125 |
+
'partial' => 1
|
126 |
+
);
|
127 |
+
}
|
128 |
+
}
|
129 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
130 |
+
if ($login === false) {
|
131 |
+
return array(
|
132 |
+
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
133 |
+
'partial' => 1
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
if($ftp_passive){
|
138 |
+
@ftp_pasv($conn_id,true);
|
139 |
+
}
|
140 |
+
|
141 |
+
@ftp_mkdir($conn_id, $ftp_remote_folder);
|
142 |
+
if ($ftp_site_folder) {
|
143 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
144 |
+
}
|
145 |
+
@ftp_mkdir($conn_id, $ftp_remote_folder);
|
146 |
+
|
147 |
+
$upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
|
148 |
+
|
149 |
+
if ($upload === false) { //Try ascii
|
150 |
+
$upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
|
151 |
+
}
|
152 |
+
ftp_close($conn_id);
|
153 |
+
|
154 |
+
if ($upload === false) {
|
155 |
+
return array(
|
156 |
+
'error' => 'Failed to upload file to FTP. Please check your specified path.',
|
157 |
+
'partial' => 1
|
158 |
+
);
|
159 |
+
}
|
160 |
+
|
161 |
+
return true;
|
162 |
+
}
|
163 |
+
|
164 |
+
function remove_ftp_backup($args)
|
165 |
+
{
|
166 |
+
extract($args);
|
167 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
168 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
169 |
+
if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
|
170 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
171 |
+
} else if (function_exists('ftp_connect')) {
|
172 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
173 |
+
}
|
174 |
+
|
175 |
+
if ($conn_id) {
|
176 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
177 |
+
if ($ftp_site_folder)
|
178 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
179 |
+
|
180 |
+
if($ftp_passive){
|
181 |
+
@ftp_pasv($conn_id,true);
|
182 |
+
}
|
183 |
+
|
184 |
+
$delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
|
185 |
+
|
186 |
+
ftp_close($conn_id);
|
187 |
+
}
|
188 |
+
|
189 |
+
}
|
190 |
+
|
191 |
+
function get_ftp_backup($args)
|
192 |
+
{
|
193 |
+
extract($args);
|
194 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
195 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
196 |
+
if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
|
197 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
198 |
+
|
199 |
+
} else if (function_exists('ftp_connect')) {
|
200 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
201 |
+
if ($conn_id === false) {
|
202 |
+
return false;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
206 |
+
if ($login === false) {
|
207 |
+
return false;
|
208 |
+
} else {
|
209 |
+
}
|
210 |
+
|
211 |
+
if ($ftp_site_folder)
|
212 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
213 |
+
|
214 |
+
if($ftp_passive){
|
215 |
+
@ftp_pasv($conn_id,true);
|
216 |
+
}
|
217 |
+
|
218 |
+
$temp = ABSPATH . 'iwp_temp_backup.zip';
|
219 |
+
$get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
|
220 |
+
if ($get === false) {
|
221 |
+
return false;
|
222 |
+
} else {
|
223 |
+
|
224 |
+
}
|
225 |
+
ftp_close($conn_id);
|
226 |
+
|
227 |
+
return $temp;
|
228 |
+
}
|
229 |
+
|
230 |
+
function amazons3_backup($args)
|
231 |
+
{
|
232 |
+
if ($this->iwp_mmb_function_exists('curl_init')) {
|
233 |
+
require_once($iwp_mmb_plugin_dir.'/lib/s3.php');
|
234 |
+
extract($args);
|
235 |
+
|
236 |
+
if ($as3_site_folder == true)
|
237 |
+
$as3_directory .= '/' . $this->site_name;
|
238 |
+
|
239 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
240 |
+
|
241 |
+
$s3 = new S3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
|
242 |
+
|
243 |
+
$s3->putBucket($as3_bucket, S3::ACL_PUBLIC_READ);
|
244 |
+
|
245 |
+
if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), S3::ACL_PRIVATE)) {
|
246 |
+
return true;
|
247 |
+
} else {
|
248 |
+
return array(
|
249 |
+
'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
|
250 |
+
'partial' => 1
|
251 |
+
);
|
252 |
+
}
|
253 |
+
} else {
|
254 |
+
return array(
|
255 |
+
'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
|
256 |
+
'partial' => 1
|
257 |
+
);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
function remove_amazons3_backup($args)
|
262 |
+
{
|
263 |
+
require_once($iwp_mmb_plugin_dir.'/lib/s3.php');
|
264 |
+
extract($args);
|
265 |
+
if ($as3_site_folder == true)
|
266 |
+
$as3_directory .= '/' . $this->site_name;
|
267 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
268 |
+
$s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
|
269 |
+
$s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
|
270 |
+
}
|
271 |
+
|
272 |
+
function get_amazons3_backup($args)
|
273 |
+
{
|
274 |
+
require_once($iwp_mmb_plugin_dir.'/lib/s3.php');
|
275 |
+
extract($args);
|
276 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
277 |
+
$s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
|
278 |
+
if ($as3_site_folder == true)
|
279 |
+
$as3_directory .= '/' . $this->site_name;
|
280 |
+
|
281 |
+
$temp = ABSPATH . 'iwp_temp_backup.zip';
|
282 |
+
$s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
|
283 |
+
|
284 |
+
return $temp;
|
285 |
+
}
|
286 |
+
|
287 |
+
function dropbox_backup($args)
|
288 |
+
{
|
289 |
+
|
290 |
+
extract($args);
|
291 |
+
|
292 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
293 |
+
//New way
|
294 |
+
require_once($iwp_mmb_plugin_dir.'/lib/dropbox.oauth.php');
|
295 |
+
|
296 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
297 |
+
$dropbox->setOAuthToken($oauth_token);
|
298 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
299 |
+
|
300 |
+
if ($dropbox_site_folder == true)
|
301 |
+
$dropbox_destination .= '/' . $this->site_name;
|
302 |
+
|
303 |
+
try{
|
304 |
+
|
305 |
+
$dropbox->filesPost($dropbox_destination, $backup_file,true);
|
306 |
+
|
307 |
+
} catch(Exception $e){
|
308 |
+
return array(
|
309 |
+
'error' => 'Dropbox upload error. '.$e->getMessage()
|
310 |
+
);
|
311 |
+
}
|
312 |
+
|
313 |
+
return true;
|
314 |
+
|
315 |
+
} else {
|
316 |
+
//old way
|
317 |
+
require_once($iwp_mmb_plugin_dir.'/lib/dropbox.php');
|
318 |
+
// extract($args);
|
319 |
+
|
320 |
+
//$email, $password, $backup_file, $destination, $dropbox_site_folder
|
321 |
+
|
322 |
+
$size = ceil(filesize($backup_file) / 1024);
|
323 |
+
if ($size > 300000) {
|
324 |
+
return array(
|
325 |
+
'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
|
326 |
+
'partial' => 1
|
327 |
+
);
|
328 |
+
}
|
329 |
+
|
330 |
+
if ($dropbox_site_folder == true)
|
331 |
+
$dropbox_destination .= '/' . $this->site_name;
|
332 |
+
|
333 |
+
try {
|
334 |
+
$uploader = new DropboxUploader($dropbox_username, $dropbox_password);
|
335 |
+
$uploader->upload($backup_file, $dropbox_destination);
|
336 |
+
}
|
337 |
+
catch (Exception $e) {
|
338 |
+
return array(
|
339 |
+
'error' => $e->getMessage(),
|
340 |
+
'partial' => 1
|
341 |
+
);
|
342 |
+
}
|
343 |
+
|
344 |
+
return true;
|
345 |
+
}
|
346 |
+
|
347 |
+
}
|
348 |
+
|
349 |
+
function remove_dropbox_backup($args){
|
350 |
+
extract($args);
|
351 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
352 |
+
//New way
|
353 |
+
require_once($iwp_mmb_plugin_dir.'/lib/dropbox.oauth.php');
|
354 |
+
|
355 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
356 |
+
$dropbox->setOAuthToken($oauth_token);
|
357 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
358 |
+
|
359 |
+
if ($dropbox_site_folder == true)
|
360 |
+
$dropbox_destination .= '/' . $this->site_name;
|
361 |
+
|
362 |
+
try{
|
363 |
+
$dropbox->fileopsDelete($dropbox_destination.'/'.$backup_file, true);
|
364 |
+
} catch(Exception $e){
|
365 |
+
|
366 |
+
}
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
function get_dropbox_backup($args){
|
371 |
+
extract($args);
|
372 |
+
|
373 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
374 |
+
//New way
|
375 |
+
require_once($iwp_mmb_plugin_dir.'/lib/dropbox.oauth.php');
|
376 |
+
|
377 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
378 |
+
$dropbox->setOAuthToken($oauth_token);
|
379 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
380 |
+
|
381 |
+
if ($dropbox_site_folder == true)
|
382 |
+
$dropbox_destination .= '/' . $this->site_name;
|
383 |
+
|
384 |
+
$temp = ABSPATH . 'iwp_temp_backup.zip';
|
385 |
+
|
386 |
+
try{
|
387 |
+
$file = $dropbox->filesGet($dropbox_destination.'/'.$backup_file, true);
|
388 |
+
|
389 |
+
if(isset($file['data']) && !empty($file['data']) )
|
390 |
+
$stream = base64_decode($file['data']);
|
391 |
+
else
|
392 |
+
return false;
|
393 |
+
|
394 |
+
$handle = @fopen($temp, 'w+');
|
395 |
+
$result = fwrite($handle,$stream);
|
396 |
+
fclose($handle);
|
397 |
+
|
398 |
+
if($result)
|
399 |
+
return $temp;
|
400 |
+
else
|
401 |
+
return false;
|
402 |
+
|
403 |
+
} catch(Exception $e){
|
404 |
+
|
405 |
+
|
406 |
+
return false;
|
407 |
+
}
|
408 |
+
|
409 |
+
} else {
|
410 |
+
return false;
|
411 |
+
}
|
412 |
+
}
|
413 |
+
|
414 |
+
function email_backup($args)
|
415 |
+
{
|
416 |
+
$email = $args['email'];
|
417 |
+
|
418 |
+
if (!is_email($email)) {
|
419 |
+
return array(
|
420 |
+
'error' => 'Your email (' . $email . ') is not correct'
|
421 |
+
);
|
422 |
+
}
|
423 |
+
$backup_file = $args['file_path'];
|
424 |
+
$task_name = isset($args['task_name']) ? $args['task_name'] : '';
|
425 |
+
if (file_exists($backup_file) && $email) {
|
426 |
+
$attachments = array(
|
427 |
+
$backup_file
|
428 |
+
);
|
429 |
+
$headers = 'From: InfiniteWP <no-reply@infinitewp.com>' . "\r\n";
|
430 |
+
$subject = "InfiniteWP - " . $task_name . " - " . $this->site_name;
|
431 |
+
ob_start();
|
432 |
+
$result = wp_mail($email, $subject, $subject, $headers, $attachments);
|
433 |
+
ob_end_clean();
|
434 |
+
|
435 |
+
}
|
436 |
+
|
437 |
+
if (!$result) {
|
438 |
+
return array(
|
439 |
+
'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
|
440 |
+
);
|
441 |
+
}
|
442 |
+
return true;
|
443 |
+
|
444 |
+
}
|
445 |
+
|
446 |
+
function update_tasks($tasks)
|
447 |
+
{
|
448 |
+
$this->tasks = $tasks;
|
449 |
+
update_option('iwp_client_backup_tasks', $tasks);
|
450 |
+
}*/
|
451 |
+
|
452 |
+
}
|
453 |
+
?>
|
backup.class.php
CHANGED
@@ -121,8 +121,18 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
121 |
'removed' => true
|
122 |
);
|
123 |
} else {
|
|
|
|
|
|
|
|
|
124 |
|
125 |
$before[$task_name]['task_args'] = $args;
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
$return = $before[$task_name];
|
127 |
}
|
128 |
|
@@ -224,6 +234,50 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
224 |
|
225 |
}
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
/*
|
228 |
* If Task Name not set then it's manual backup
|
229 |
* Backup args:
|
@@ -360,7 +414,24 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
360 |
'file_url' => $backup_url
|
361 |
);
|
362 |
}
|
363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
$temp = $backup_settings[$task_name]['task_results'];
|
365 |
$temp = @array_values($temp);
|
366 |
$paths['time'] = time();
|
@@ -380,8 +451,68 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
380 |
}
|
381 |
|
382 |
//Additional: Email, ftp, amazon_s3, dropbox...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
|
384 |
-
if ($task_name != 'Backup Now') {
|
385 |
if ($del_host_file) {
|
386 |
@unlink($backup_file);
|
387 |
}
|
@@ -749,6 +880,44 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
749 |
$unlink_file = false; //Don't delete file if stored on server
|
750 |
}
|
751 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
752 |
$what = $tasks[$task_name]['task_args']['what'];
|
753 |
}
|
754 |
|
@@ -930,11 +1099,8 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
930 |
}
|
931 |
|
932 |
}
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
return true;
|
938 |
}
|
939 |
|
940 |
function restore_db()
|
@@ -1212,6 +1378,428 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1212 |
return $reqs;
|
1213 |
}
|
1214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1215 |
//Parse task arguments for info on IWP Admin Panel
|
1216 |
function get_backup_stats()
|
1217 |
{
|
@@ -1236,6 +1824,22 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1236 |
return $stats;
|
1237 |
}
|
1238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1239 |
function remove_old_backups($task_name)
|
1240 |
{
|
1241 |
//Check for previous failed backups first
|
@@ -1259,6 +1863,27 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1259 |
@unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
|
1260 |
}
|
1261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1262 |
//Remove database backup info
|
1263 |
unset($backups[$task_name]['task_results'][$i]);
|
1264 |
|
@@ -1293,6 +1918,33 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1293 |
if (isset($backup['server'])) {
|
1294 |
@unlink($backup['server']['file_path']);
|
1295 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1296 |
unset($backups[$result_id]);
|
1297 |
|
1298 |
if (count($backups)) {
|
@@ -1327,7 +1979,7 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1327 |
|
1328 |
|
1329 |
//clean_old folder?
|
1330 |
-
if ((basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
|
1331 |
foreach ($files as $file) {
|
1332 |
@unlink($file);
|
1333 |
}
|
@@ -1335,7 +1987,7 @@ class IWP_MMB_Backup extends IWP_MMB_Core
|
|
1335 |
@rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client'));
|
1336 |
}
|
1337 |
|
1338 |
-
|
1339 |
foreach ($new as $b) {
|
1340 |
$files[] = $b;
|
1341 |
}
|
121 |
'removed' => true
|
122 |
);
|
123 |
} else {
|
124 |
+
|
125 |
+
if (is_array($params['account_info'])) { //only if sends from IWP Admin Panel first time(secure data)
|
126 |
+
$args['account_info'] = $account_info;
|
127 |
+
}
|
128 |
|
129 |
$before[$task_name]['task_args'] = $args;
|
130 |
+
//$before[$task_name]['task_args'] = $task_name;
|
131 |
+
|
132 |
+
if (strlen($args['schedule']))
|
133 |
+
$before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
|
134 |
+
$before[$task_name]['task_args']['task_name'] = $task_name;
|
135 |
+
|
136 |
$return = $before[$task_name];
|
137 |
}
|
138 |
|
234 |
|
235 |
}
|
236 |
|
237 |
+
|
238 |
+
function task_now($task_name){
|
239 |
+
|
240 |
+
$settings = $this->tasks;
|
241 |
+
if(!array_key_exists($task_name,$settings)){
|
242 |
+
return array('error' => $task_name." does not exist.");
|
243 |
+
} else {
|
244 |
+
$setting = $settings[$task_name];
|
245 |
+
}
|
246 |
+
|
247 |
+
$this->set_backup_task(array(
|
248 |
+
'task_name' => $task_name,
|
249 |
+
'args' => $settings[$task_name]['task_args'],
|
250 |
+
'time' => time()
|
251 |
+
));
|
252 |
+
|
253 |
+
//Run backup
|
254 |
+
$result = $this->backup($setting['task_args'], $task_name);
|
255 |
+
|
256 |
+
//Check for error
|
257 |
+
if (is_array($result) && array_key_exists('error', $result)) {
|
258 |
+
$this->set_backup_task(array(
|
259 |
+
'task_name' => $task_name,
|
260 |
+
'args' => $settings[$task_name]['task_args'],
|
261 |
+
'error' => $result['error']
|
262 |
+
));
|
263 |
+
return $result;
|
264 |
+
} else {
|
265 |
+
return $this->get_backup_stats();
|
266 |
+
}
|
267 |
+
|
268 |
+
}
|
269 |
+
|
270 |
+
function delete_task_now($task_name){
|
271 |
+
$tasks = $this->tasks;
|
272 |
+
unset($tasks[$task_name]);
|
273 |
+
$this->update_tasks($tasks);
|
274 |
+
$this->cleanup();
|
275 |
+
|
276 |
+
return $task_name;
|
277 |
+
|
278 |
+
}
|
279 |
+
|
280 |
+
|
281 |
/*
|
282 |
* If Task Name not set then it's manual backup
|
283 |
* Backup args:
|
414 |
'file_url' => $backup_url
|
415 |
);
|
416 |
}
|
417 |
+
|
418 |
+
|
419 |
+
if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_ftp'])) {
|
420 |
+
$paths['ftp'] = basename($backup_url);
|
421 |
+
}
|
422 |
+
|
423 |
+
if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_amazon_s3'])) {
|
424 |
+
$paths['amazons3'] = basename($backup_url);
|
425 |
+
}
|
426 |
+
|
427 |
+
if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_dropbox'])) {
|
428 |
+
$paths['dropbox'] = basename($backup_url);
|
429 |
+
}
|
430 |
+
|
431 |
+
if (isset($backup_settings[$task_name]['task_args']['account_info']['iwp_email'])) {
|
432 |
+
$paths['email'] = basename($backup_url);
|
433 |
+
}
|
434 |
+
|
435 |
$temp = $backup_settings[$task_name]['task_results'];
|
436 |
$temp = @array_values($temp);
|
437 |
$paths['time'] = time();
|
451 |
}
|
452 |
|
453 |
//Additional: Email, ftp, amazon_s3, dropbox...
|
454 |
+
/*
|
455 |
+
//IWP Remove starts here //IWP Remove ends here
|
456 |
+
*/
|
457 |
+
if ($task_name != 'Backup Now') {
|
458 |
+
|
459 |
+
if (isset($account_info['iwp_ftp']) && !empty($account_info['iwp_ftp'])) {
|
460 |
+
$this->update_status($task_name, $this->statuses['ftp']);
|
461 |
+
$account_info['iwp_ftp']['backup_file'] = $backup_file;
|
462 |
+
$ftp_result = $this->ftp_backup($account_info['iwp_ftp']);
|
463 |
+
|
464 |
+
if ($ftp_result !== true && $del_host_file) {
|
465 |
+
@unlink($backup_file);
|
466 |
+
}
|
467 |
+
|
468 |
+
if (is_array($ftp_result) && isset($ftp_result['error'])) {
|
469 |
+
return $ftp_result;
|
470 |
+
}
|
471 |
+
$this->wpdb_reconnect();
|
472 |
+
$this->update_status($task_name, $this->statuses['ftp'], true);
|
473 |
+
}
|
474 |
+
|
475 |
+
if (isset($account_info['iwp_amazon_s3']) && !empty($account_info['iwp_amazon_s3'])) {
|
476 |
+
$this->update_status($task_name, $this->statuses['s3']);
|
477 |
+
$account_info['iwp_amazon_s3']['backup_file'] = $backup_file;
|
478 |
+
$amazons3_result = $this->amazons3_backup($account_info['iwp_amazon_s3']);
|
479 |
+
if ($amazons3_result !== true && $del_host_file) {
|
480 |
+
@unlink($backup_file);
|
481 |
+
}
|
482 |
+
if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
|
483 |
+
return $amazons3_result;
|
484 |
+
}
|
485 |
+
$this->wpdb_reconnect();
|
486 |
+
$this->update_status($task_name, $this->statuses['s3'], true);
|
487 |
+
}
|
488 |
+
|
489 |
+
if (isset($account_info['iwp_dropbox']) && !empty($account_info['iwp_dropbox'])) {
|
490 |
+
$this->update_status($task_name, $this->statuses['dropbox']);
|
491 |
+
$account_info['iwp_dropbox']['backup_file'] = $backup_file;
|
492 |
+
$dropbox_result = $this->dropbox_backup($account_info['iwp_dropbox']);
|
493 |
+
if ($dropbox_result !== true && $del_host_file) {
|
494 |
+
@unlink($backup_file);
|
495 |
+
}
|
496 |
+
|
497 |
+
if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
|
498 |
+
return $dropbox_result;
|
499 |
+
}
|
500 |
+
$this->wpdb_reconnect();
|
501 |
+
$this->update_status($task_name, $this->statuses['dropbox'], true);
|
502 |
+
}
|
503 |
+
|
504 |
+
if (isset($account_info['iwp_email']) && !empty($account_info['iwp_email'])) {
|
505 |
+
$this->update_status($task_name, $this->statuses['email']);
|
506 |
+
$account_info['iwp_email']['task_name'] = $task_name;
|
507 |
+
$account_info['iwp_email']['file_path'] = $backup_file;
|
508 |
+
|
509 |
+
$email_result = $this->email_backup($account_info['iwp_email']);
|
510 |
+
if (is_array($email_result) && isset($email_result['error'])) {
|
511 |
+
return $email_result;
|
512 |
+
}
|
513 |
+
$this->update_status($task_name, $this->statuses['email'], true);
|
514 |
+
}
|
515 |
|
|
|
516 |
if ($del_host_file) {
|
517 |
@unlink($backup_file);
|
518 |
}
|
880 |
$unlink_file = false; //Don't delete file if stored on server
|
881 |
}
|
882 |
|
883 |
+
/*
|
884 |
+
//IWP Remove starts here//IWP Remove ends here
|
885 |
+
*/
|
886 |
+
|
887 |
+
elseif (isset($task['task_results'][$result_id]['ftp'])) {
|
888 |
+
$ftp_file = $task['task_results'][$result_id]['ftp'];
|
889 |
+
$args = $task['task_args']['account_info']['iwp_ftp'];
|
890 |
+
$args['backup_file'] = $ftp_file;
|
891 |
+
$backup_file = $this->get_ftp_backup($args);
|
892 |
+
if ($backup_file == false) {
|
893 |
+
return array(
|
894 |
+
'error' => 'Failed to download file from FTP.'
|
895 |
+
);
|
896 |
+
}
|
897 |
+
} elseif (isset($task['task_results'][$result_id]['amazons3'])) {
|
898 |
+
$amazons3_file = $task['task_results'][$result_id]['amazons3'];
|
899 |
+
$args = $task['task_args']['account_info']['iwp_amazon_s3'];
|
900 |
+
$args['backup_file'] = $ftp_file;
|
901 |
+
$backup_file = $this->get_amazons3_backup($args);
|
902 |
+
if ($backup_file == false) {
|
903 |
+
return array(
|
904 |
+
'error' => 'Failed to download file from Amazon S3.'
|
905 |
+
);
|
906 |
+
}
|
907 |
+
} elseif(isset($task['task_results'][$result_id]['dropbox'])){
|
908 |
+
$dropbox_file = $task['task_results'][$result_id]['dropbox'];
|
909 |
+
$args = $task['task_args']['account_info']['iwp_dropbox'];
|
910 |
+
$args['backup_file'] = $dropbox_file;
|
911 |
+
$backup_file = $this->get_dropbox_backup($args);
|
912 |
+
|
913 |
+
if ($backup_file == false) {
|
914 |
+
return array(
|
915 |
+
'error' => 'Failed to download file from Dropbox.'
|
916 |
+
);
|
917 |
+
}
|
918 |
+
}
|
919 |
+
|
920 |
+
|
921 |
$what = $tasks[$task_name]['task_args']['what'];
|
922 |
}
|
923 |
|
1099 |
}
|
1100 |
|
1101 |
}
|
1102 |
+
|
1103 |
+
return !empty($new_user) ? $new_user : true ;
|
|
|
|
|
|
|
1104 |
}
|
1105 |
|
1106 |
function restore_db()
|
1378 |
return $reqs;
|
1379 |
}
|
1380 |
|
1381 |
+
function ftp_backup($args)
|
1382 |
+
{
|
1383 |
+
extract($args);
|
1384 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
|
1385 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
1386 |
+
if ($ftp_ssl) {
|
1387 |
+
if (function_exists('ftp_ssl_connect')) {
|
1388 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
1389 |
+
} else {
|
1390 |
+
return array(
|
1391 |
+
'error' => 'Your server doesn\'t support SFTP',
|
1392 |
+
'partial' => 1
|
1393 |
+
);
|
1394 |
+
}
|
1395 |
+
} else {
|
1396 |
+
if (function_exists('ftp_connect')) {
|
1397 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
1398 |
+
if ($conn_id === false) {
|
1399 |
+
return array(
|
1400 |
+
'error' => 'Failed to connect to ' . $ftp_hostname,
|
1401 |
+
'partial' => 1
|
1402 |
+
);
|
1403 |
+
}
|
1404 |
+
} else {
|
1405 |
+
return array(
|
1406 |
+
'error' => 'Your server doesn\'t support FTP',
|
1407 |
+
'partial' => 1
|
1408 |
+
);
|
1409 |
+
}
|
1410 |
+
}
|
1411 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
1412 |
+
if ($login === false) {
|
1413 |
+
return array(
|
1414 |
+
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
1415 |
+
'partial' => 1
|
1416 |
+
);
|
1417 |
+
}
|
1418 |
+
|
1419 |
+
if($ftp_passive){
|
1420 |
+
@ftp_pasv($conn_id,true);
|
1421 |
+
}
|
1422 |
+
|
1423 |
+
@ftp_mkdir($conn_id, $ftp_remote_folder);
|
1424 |
+
if ($ftp_site_folder) {
|
1425 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
1426 |
+
}
|
1427 |
+
@ftp_mkdir($conn_id, $ftp_remote_folder);
|
1428 |
+
|
1429 |
+
$upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
|
1430 |
+
|
1431 |
+
if ($upload === false) { //Try ascii
|
1432 |
+
$upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
|
1433 |
+
}
|
1434 |
+
ftp_close($conn_id);
|
1435 |
+
|
1436 |
+
if ($upload === false) {
|
1437 |
+
return array(
|
1438 |
+
'error' => 'Failed to upload file to FTP. Please check your specified path.',
|
1439 |
+
'partial' => 1
|
1440 |
+
);
|
1441 |
+
}
|
1442 |
+
|
1443 |
+
return true;
|
1444 |
+
}
|
1445 |
+
|
1446 |
+
function remove_ftp_backup($args)
|
1447 |
+
{
|
1448 |
+
extract($args);
|
1449 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
1450 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
1451 |
+
if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
|
1452 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
1453 |
+
} else if (function_exists('ftp_connect')) {
|
1454 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
1455 |
+
}
|
1456 |
+
|
1457 |
+
if ($conn_id) {
|
1458 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
1459 |
+
if ($ftp_site_folder)
|
1460 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
1461 |
+
|
1462 |
+
if($ftp_passive){
|
1463 |
+
@ftp_pasv($conn_id,true);
|
1464 |
+
}
|
1465 |
+
|
1466 |
+
$delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
|
1467 |
+
|
1468 |
+
ftp_close($conn_id);
|
1469 |
+
}
|
1470 |
+
|
1471 |
+
}
|
1472 |
+
|
1473 |
+
function get_ftp_backup($args)
|
1474 |
+
{
|
1475 |
+
extract($args);
|
1476 |
+
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
1477 |
+
$port = $ftp_port ? $ftp_port : 21; //default port is 21
|
1478 |
+
if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
|
1479 |
+
$conn_id = ftp_ssl_connect($ftp_hostname,$port);
|
1480 |
+
|
1481 |
+
} else if (function_exists('ftp_connect')) {
|
1482 |
+
$conn_id = ftp_connect($ftp_hostname,$port);
|
1483 |
+
if ($conn_id === false) {
|
1484 |
+
return false;
|
1485 |
+
}
|
1486 |
+
}
|
1487 |
+
$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
|
1488 |
+
if ($login === false) {
|
1489 |
+
return false;
|
1490 |
+
} else {
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
if ($ftp_site_folder)
|
1494 |
+
$ftp_remote_folder .= '/' . $this->site_name;
|
1495 |
+
|
1496 |
+
if($ftp_passive){
|
1497 |
+
@ftp_pasv($conn_id,true);
|
1498 |
+
}
|
1499 |
+
|
1500 |
+
$temp = ABSPATH . 'iwp_temp_backup.zip';
|
1501 |
+
$get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
|
1502 |
+
if ($get === false) {
|
1503 |
+
return false;
|
1504 |
+
} else {
|
1505 |
+
}
|
1506 |
+
ftp_close($conn_id);
|
1507 |
+
|
1508 |
+
return $temp;
|
1509 |
+
}
|
1510 |
+
|
1511 |
+
|
1512 |
+
function dropbox_backup($args)
|
1513 |
+
{
|
1514 |
+
|
1515 |
+
extract($args);
|
1516 |
+
|
1517 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
1518 |
+
//New way
|
1519 |
+
require_once('lib/dropbox.oauth.php');
|
1520 |
+
|
1521 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
1522 |
+
$dropbox->setOAuthToken($oauth_token);
|
1523 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
1524 |
+
|
1525 |
+
if ($dropbox_site_folder == true)
|
1526 |
+
$dropbox_destination .= '/' . $this->site_name;
|
1527 |
+
|
1528 |
+
try{
|
1529 |
+
|
1530 |
+
$dropbox->filesPost($dropbox_destination, $backup_file,true);
|
1531 |
+
|
1532 |
+
} catch(Exception $e){
|
1533 |
+
return array(
|
1534 |
+
'error' => 'Dropbox upload error. '.$e->getMessage()
|
1535 |
+
);
|
1536 |
+
}
|
1537 |
+
|
1538 |
+
return true;
|
1539 |
+
|
1540 |
+
} else {
|
1541 |
+
//old way
|
1542 |
+
require_once('lib/dropbox.php');
|
1543 |
+
// extract($args);
|
1544 |
+
|
1545 |
+
//$email, $password, $backup_file, $destination, $dropbox_site_folder
|
1546 |
+
|
1547 |
+
$size = ceil(filesize($backup_file) / 1024);
|
1548 |
+
if ($size > 300000) {
|
1549 |
+
return array(
|
1550 |
+
'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
|
1551 |
+
'partial' => 1
|
1552 |
+
);
|
1553 |
+
}
|
1554 |
+
|
1555 |
+
if ($dropbox_site_folder == true)
|
1556 |
+
$dropbox_destination .= '/' . $this->site_name;
|
1557 |
+
|
1558 |
+
try {
|
1559 |
+
$uploader = new DropboxUploader($dropbox_username, $dropbox_password);
|
1560 |
+
$uploader->upload($backup_file, $dropbox_destination);
|
1561 |
+
}
|
1562 |
+
catch (Exception $e) {
|
1563 |
+
return array(
|
1564 |
+
'error' => $e->getMessage(),
|
1565 |
+
'partial' => 1
|
1566 |
+
);
|
1567 |
+
}
|
1568 |
+
|
1569 |
+
return true;
|
1570 |
+
}
|
1571 |
+
|
1572 |
+
}
|
1573 |
+
|
1574 |
+
function remove_dropbox_backup($args){
|
1575 |
+
extract($args);
|
1576 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
1577 |
+
//New way
|
1578 |
+
require_once('lib/dropbox.oauth.php');
|
1579 |
+
|
1580 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
1581 |
+
$dropbox->setOAuthToken($oauth_token);
|
1582 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
1583 |
+
|
1584 |
+
if ($dropbox_site_folder == true)
|
1585 |
+
$dropbox_destination .= '/' . $this->site_name;
|
1586 |
+
|
1587 |
+
try{
|
1588 |
+
$dropbox->fileopsDelete($dropbox_destination.'/'.$backup_file, true);
|
1589 |
+
} catch(Exception $e){
|
1590 |
+
|
1591 |
+
}
|
1592 |
+
}
|
1593 |
+
}
|
1594 |
+
|
1595 |
+
function get_dropbox_backup($args){
|
1596 |
+
extract($args);
|
1597 |
+
|
1598 |
+
if(isset($consumer_secret) && !empty($consumer_secret)){
|
1599 |
+
//New way
|
1600 |
+
require_once('lib/dropbox.oauth.php');
|
1601 |
+
|
1602 |
+
$dropbox = new Dropbox($consumer_key, $consumer_secret);
|
1603 |
+
$dropbox->setOAuthToken($oauth_token);
|
1604 |
+
$dropbox->setOAuthTokenSecret($oauth_token_secret);
|
1605 |
+
|
1606 |
+
if ($dropbox_site_folder == true)
|
1607 |
+
$dropbox_destination .= '/' . $this->site_name;
|
1608 |
+
|
1609 |
+
$temp = ABSPATH . 'mwp_temp_backup.zip';
|
1610 |
+
|
1611 |
+
try{
|
1612 |
+
$file = $dropbox->filesGet($dropbox_destination.'/'.$backup_file, true);
|
1613 |
+
|
1614 |
+
if(isset($file['data']) && !empty($file['data']) )
|
1615 |
+
$stream = base64_decode($file['data']);
|
1616 |
+
else
|
1617 |
+
return false;
|
1618 |
+
|
1619 |
+
$handle = @fopen($temp, 'w+');
|
1620 |
+
$result = fwrite($handle,$stream);
|
1621 |
+
fclose($handle);
|
1622 |
+
|
1623 |
+
if($result)
|
1624 |
+
return $temp;
|
1625 |
+
else
|
1626 |
+
return false;
|
1627 |
+
|
1628 |
+
} catch(Exception $e){
|
1629 |
+
|
1630 |
+
|
1631 |
+
return false;
|
1632 |
+
}
|
1633 |
+
|
1634 |
+
} else {
|
1635 |
+
return false;
|
1636 |
+
}
|
1637 |
+
|
1638 |
+
|
1639 |
+
}
|
1640 |
+
|
1641 |
+
function amazons3_backup($args)
|
1642 |
+
{
|
1643 |
+
if ($this->iwp_mmb_function_exists('curl_init')) {
|
1644 |
+
require_once('lib/s3.php');
|
1645 |
+
extract($args);
|
1646 |
+
|
1647 |
+
if ($as3_site_folder == true)
|
1648 |
+
$as3_directory .= '/' . $this->site_name;
|
1649 |
+
|
1650 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
1651 |
+
|
1652 |
+
$s3 = new S3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
|
1653 |
+
|
1654 |
+
$s3->putBucket($as3_bucket, S3::ACL_PUBLIC_READ);
|
1655 |
+
|
1656 |
+
if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), S3::ACL_PRIVATE)) {
|
1657 |
+
return true;
|
1658 |
+
} else {
|
1659 |
+
return array(
|
1660 |
+
'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
|
1661 |
+
'partial' => 1
|
1662 |
+
);
|
1663 |
+
}
|
1664 |
+
|
1665 |
+
}
|
1666 |
+
else {
|
1667 |
+
return array(
|
1668 |
+
'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
|
1669 |
+
'partial' => 1
|
1670 |
+
);
|
1671 |
+
}
|
1672 |
+
}
|
1673 |
+
|
1674 |
+
function remove_amazons3_backup($args)
|
1675 |
+
{
|
1676 |
+
if ($this->iwp_mmb_function_exists('curl_init')) {
|
1677 |
+
require_once('lib/s3.php');
|
1678 |
+
extract($args);
|
1679 |
+
if ($as3_site_folder == true)
|
1680 |
+
$as3_directory .= '/' . $this->site_name;
|
1681 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
1682 |
+
try{
|
1683 |
+
$s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
|
1684 |
+
$s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
|
1685 |
+
} catch (Exception $e){
|
1686 |
+
|
1687 |
+
}
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
|
1691 |
+
function get_amazons3_backup($args)
|
1692 |
+
{
|
1693 |
+
require_once('lib/s3.php');
|
1694 |
+
extract($args);
|
1695 |
+
$endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
|
1696 |
+
$temp = '';
|
1697 |
+
try{
|
1698 |
+
$s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
|
1699 |
+
if ($as3_site_folder == true)
|
1700 |
+
$as3_directory .= '/' . $this->site_name;
|
1701 |
+
|
1702 |
+
$temp = ABSPATH . 'iwp_temp_backup.zip';
|
1703 |
+
$s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
|
1704 |
+
} catch (Exception $e){
|
1705 |
+
return $temp;
|
1706 |
+
}
|
1707 |
+
return $temp;
|
1708 |
+
}
|
1709 |
+
//IWP Remove ends here
|
1710 |
+
|
1711 |
+
|
1712 |
+
function schedule_next($type, $schedule)
|
1713 |
+
{
|
1714 |
+
$schedule = explode("|", $schedule);
|
1715 |
+
if (empty($schedule))
|
1716 |
+
return false;
|
1717 |
+
switch ($type) {
|
1718 |
+
|
1719 |
+
case 'daily':
|
1720 |
+
|
1721 |
+
if (isset($schedule[1]) && $schedule[1]) {
|
1722 |
+
$delay_time = $schedule[1] * 60;
|
1723 |
+
}
|
1724 |
+
|
1725 |
+
$current_hour = date("H");
|
1726 |
+
$schedule_hour = $schedule[0];
|
1727 |
+
if ($current_hour >= $schedule_hour){
|
1728 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
|
1729 |
+
//$time ='0001#'.$current_hour.'|'.$schedule_hour;
|
1730 |
+
|
1731 |
+
}
|
1732 |
+
|
1733 |
+
else{
|
1734 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
|
1735 |
+
//$time ='0000#'.$current_hour.'|'.$schedule_hour;
|
1736 |
+
}
|
1737 |
+
$time = time() + 30;
|
1738 |
+
|
1739 |
+
file_put_contents("timetest.txt", var_export($time, true).'|'.var_export($schedule_hour, true).'|'.var_export($current_hour, true));
|
1740 |
+
break;
|
1741 |
+
|
1742 |
+
|
1743 |
+
case 'weekly':
|
1744 |
+
if (isset($schedule[2]) && $schedule[2]) {
|
1745 |
+
$delay_time = $schedule[2] * 60;
|
1746 |
+
}
|
1747 |
+
$current_weekday = date('w');
|
1748 |
+
$schedule_weekday = $schedule[1];
|
1749 |
+
$current_hour = date("H");
|
1750 |
+
$schedule_hour = $schedule[0];
|
1751 |
+
|
1752 |
+
if ($current_weekday > $schedule_weekday)
|
1753 |
+
$weekday_offset = 7 - ($week_day - $task_schedule[1]);
|
1754 |
+
else
|
1755 |
+
$weekday_offset = $schedule_weekday - $current_weekday;
|
1756 |
+
|
1757 |
+
|
1758 |
+
if (!$weekday_offset) { //today is scheduled weekday
|
1759 |
+
if ($current_hour >= $schedule_hour)
|
1760 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
|
1761 |
+
else
|
1762 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
|
1763 |
+
} else {
|
1764 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
|
1765 |
+
}
|
1766 |
+
|
1767 |
+
break;
|
1768 |
+
|
1769 |
+
case 'monthly':
|
1770 |
+
if (isset($schedule[2]) && $schedule[2]) {
|
1771 |
+
$delay_time = $schedule[2] * 60;
|
1772 |
+
}
|
1773 |
+
$current_monthday = date('j');
|
1774 |
+
$schedule_monthday = $schedule[1];
|
1775 |
+
$current_hour = date("H");
|
1776 |
+
$schedule_hour = $schedule[0];
|
1777 |
+
|
1778 |
+
if ($current_monthday > $schedule_monthday) {
|
1779 |
+
$time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
|
1780 |
+
} else if ($current_monthday < $schedule_monthday) {
|
1781 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
|
1782 |
+
} else if ($current_monthday == $schedule_monthday) {
|
1783 |
+
if ($current_hour >= $schedule_hour)
|
1784 |
+
$time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
|
1785 |
+
else
|
1786 |
+
$time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
|
1787 |
+
break;
|
1788 |
+
}
|
1789 |
+
|
1790 |
+
break;
|
1791 |
+
default:
|
1792 |
+
break;
|
1793 |
+
}
|
1794 |
+
|
1795 |
+
if (isset($delay_time) && $delay_time) {
|
1796 |
+
$time += $delay_time;
|
1797 |
+
}
|
1798 |
+
|
1799 |
+
return $time;
|
1800 |
+
}
|
1801 |
+
|
1802 |
+
|
1803 |
//Parse task arguments for info on IWP Admin Panel
|
1804 |
function get_backup_stats()
|
1805 |
{
|
1824 |
return $stats;
|
1825 |
}
|
1826 |
|
1827 |
+
/*
|
1828 |
+
//IWP Remove starts here//IWP Remove ends here
|
1829 |
+
*/
|
1830 |
+
function get_next_schedules()
|
1831 |
+
{
|
1832 |
+
$stats = array();
|
1833 |
+
$tasks = $this->tasks;
|
1834 |
+
if (is_array($tasks) && !empty($tasks)) {
|
1835 |
+
foreach ($tasks as $task_name => $info) {
|
1836 |
+
$stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
|
1837 |
+
}
|
1838 |
+
}
|
1839 |
+
return $stats;
|
1840 |
+
}
|
1841 |
+
|
1842 |
+
|
1843 |
function remove_old_backups($task_name)
|
1844 |
{
|
1845 |
//Check for previous failed backups first
|
1863 |
@unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
|
1864 |
}
|
1865 |
|
1866 |
+
if (isset($backups[$task_name]['task_results'][$i]['ftp'])) {
|
1867 |
+
$ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
|
1868 |
+
$args = $backups[$task_name]['task_args']['account_info']['iwp_ftp'];
|
1869 |
+
$args['backup_file'] = $ftp_file;
|
1870 |
+
$this->remove_ftp_backup($args);
|
1871 |
+
}
|
1872 |
+
|
1873 |
+
if (isset($backups[$task_name]['task_results'][$i]['amazons3'])) {
|
1874 |
+
$amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
|
1875 |
+
$args = $backups[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
|
1876 |
+
$args['backup_file'] = $amazons3_file;
|
1877 |
+
$this->remove_amazons3_backup($args);
|
1878 |
+
}
|
1879 |
+
|
1880 |
+
if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
|
1881 |
+
//To do: dropbox remove
|
1882 |
+
$dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
|
1883 |
+
$args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
|
1884 |
+
$args['backup_file'] = $dropbox_file;
|
1885 |
+
$this->remove_dropbox_backup($args);
|
1886 |
+
}
|
1887 |
//Remove database backup info
|
1888 |
unset($backups[$task_name]['task_results'][$i]);
|
1889 |
|
1918 |
if (isset($backup['server'])) {
|
1919 |
@unlink($backup['server']['file_path']);
|
1920 |
}
|
1921 |
+
|
1922 |
+
/*
|
1923 |
+
//IWP Remove starts here//IWP Remove ends here
|
1924 |
+
*/
|
1925 |
+
//Remove from ftp
|
1926 |
+
if (isset($backup['ftp'])) {
|
1927 |
+
$ftp_file = $backup['ftp'];
|
1928 |
+
$args = $tasks[$task_name]['task_args']['account_info']['iwp_ftp'];
|
1929 |
+
$args['backup_file'] = $ftp_file;
|
1930 |
+
$this->remove_ftp_backup($args);
|
1931 |
+
}
|
1932 |
+
|
1933 |
+
if (isset($backup['amazons3'])) {
|
1934 |
+
$amazons3_file = $backup['amazons3'];
|
1935 |
+
$args = $tasks[$task_name]['task_args']['account_info']['iwp_amazon_s3'];
|
1936 |
+
$args['backup_file'] = $amazons3_file;
|
1937 |
+
$this->remove_amazons3_backup($args);
|
1938 |
+
}
|
1939 |
+
|
1940 |
+
if (isset($backup['dropbox'])) {
|
1941 |
+
$dropbox_file = $backup['dropbox'];
|
1942 |
+
$args = $tasks[$task_name]['task_args']['account_info']['iwp_dropbox'];
|
1943 |
+
$args['backup_file'] = $dropbox_file;
|
1944 |
+
$this->remove_dropbox_backup($args);
|
1945 |
+
}
|
1946 |
+
|
1947 |
+
|
1948 |
unset($backups[$result_id]);
|
1949 |
|
1950 |
if (count($backups)) {
|
1979 |
|
1980 |
|
1981 |
//clean_old folder?
|
1982 |
+
if ((basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) { //USE (!empty($files)
|
1983 |
foreach ($files as $file) {
|
1984 |
@unlink($file);
|
1985 |
}
|
1987 |
@rmdir(WP_CONTENT_DIR . '/' . md5('iwp_mmb-client'));
|
1988 |
}
|
1989 |
|
1990 |
+
// USE $new = array();
|
1991 |
foreach ($new as $b) {
|
1992 |
$files[] = $b;
|
1993 |
}
|
core.class.php
CHANGED
@@ -35,6 +35,9 @@ class IWP_MMB_Core extends IWP_MMB_Helper
|
|
35 |
var $installer_instance;
|
36 |
var $iwp_mmb_multisite;
|
37 |
var $network_admin_install;
|
|
|
|
|
|
|
38 |
private $action_call;
|
39 |
private $action_params;
|
40 |
private $iwp_mmb_pre_init_actions;
|
@@ -122,6 +125,7 @@ class IWP_MMB_Core extends IWP_MMB_Helper
|
|
122 |
'check_backup_compat' => 'iwp_mmb_check_backup_compat',
|
123 |
'scheduled_backup' => 'iwp_mmb_scheduled_backup',
|
124 |
'run_task' => 'iwp_mmb_run_task_now',
|
|
|
125 |
'execute_php_code' => 'iwp_mmb_execute_php_code',
|
126 |
'delete_backup' => 'mmm_delete_backup',
|
127 |
'remote_backup_now' => 'iwp_mmb_remote_backup_now',
|
@@ -133,7 +137,9 @@ class IWP_MMB_Core extends IWP_MMB_Helper
|
|
133 |
'edit_plugins_themes' => 'iwp_mmb_edit_plugins_themes',
|
134 |
'client_brand' => 'iwp_mmb_client_brand',
|
135 |
'set_alerts' => 'iwp_mmb_set_alerts',
|
136 |
-
'maintenance' => 'iwp_mmb_maintenance_mode'
|
|
|
|
|
137 |
);
|
138 |
|
139 |
add_action('rightnow_end', array( &$this, 'add_right_now_info' ));
|
@@ -379,6 +385,15 @@ class IWP_MMB_Core extends IWP_MMB_Helper
|
|
379 |
return $this->backup_instance;
|
380 |
}
|
381 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
/**
|
383 |
* Gets an instance of links class
|
384 |
*
|
35 |
var $installer_instance;
|
36 |
var $iwp_mmb_multisite;
|
37 |
var $network_admin_install;
|
38 |
+
|
39 |
+
var $backup_repository_instance;
|
40 |
+
|
41 |
private $action_call;
|
42 |
private $action_params;
|
43 |
private $iwp_mmb_pre_init_actions;
|
125 |
'check_backup_compat' => 'iwp_mmb_check_backup_compat',
|
126 |
'scheduled_backup' => 'iwp_mmb_scheduled_backup',
|
127 |
'run_task' => 'iwp_mmb_run_task_now',
|
128 |
+
'delete_schedule_task' => 'iwp_mmb_delete_task_now',
|
129 |
'execute_php_code' => 'iwp_mmb_execute_php_code',
|
130 |
'delete_backup' => 'mmm_delete_backup',
|
131 |
'remote_backup_now' => 'iwp_mmb_remote_backup_now',
|
137 |
'edit_plugins_themes' => 'iwp_mmb_edit_plugins_themes',
|
138 |
'client_brand' => 'iwp_mmb_client_brand',
|
139 |
'set_alerts' => 'iwp_mmb_set_alerts',
|
140 |
+
'maintenance' => 'iwp_mmb_maintenance_mode',
|
141 |
+
|
142 |
+
'backup_repository' => 'iwp_mmb_backup_repository'
|
143 |
);
|
144 |
|
145 |
add_action('rightnow_end', array( &$this, 'add_right_now_info' ));
|
385 |
return $this->backup_instance;
|
386 |
}
|
387 |
|
388 |
+
function get_backup_repository_instance()
|
389 |
+
{
|
390 |
+
if (!isset($this->backup_repository_instance)) {
|
391 |
+
$this->backup_repository_instance = new IWP_MMB_Backup_Repository();
|
392 |
+
}
|
393 |
+
|
394 |
+
return $this->backup_repository_instance;
|
395 |
+
}
|
396 |
+
|
397 |
/**
|
398 |
* Gets an instance of links class
|
399 |
*
|
helper.class.php
CHANGED
@@ -16,6 +16,9 @@
|
|
16 |
* www.prelovac.com
|
17 |
**************************************************************/
|
18 |
|
|
|
|
|
|
|
19 |
class IWP_MMB_Helper
|
20 |
{
|
21 |
/**
|
@@ -357,7 +360,7 @@ class IWP_MMB_Helper
|
|
357 |
);
|
358 |
}
|
359 |
|
360 |
-
if (
|
361 |
$verify = openssl_verify($data, $signature, $pl_key);
|
362 |
if ($verify == 1) {
|
363 |
$message_id = $this->set_client_message_id($message_id);
|
@@ -497,10 +500,5 @@ class IWP_MMB_Helper
|
|
497 |
die('Error downloading file ' . $url);
|
498 |
return $file_name;
|
499 |
}
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
}
|
506 |
?>
|
16 |
* www.prelovac.com
|
17 |
**************************************************************/
|
18 |
|
19 |
+
if(!defined('MMB_WORKER_VERSION'))
|
20 |
+
define('MMB_WORKER_VERSION', '0');
|
21 |
+
|
22 |
class IWP_MMB_Helper
|
23 |
{
|
24 |
/**
|
360 |
);
|
361 |
}
|
362 |
|
363 |
+
if (checkOpenSSL() && !$this->get_random_signature()) {
|
364 |
$verify = openssl_verify($data, $signature, $pl_key);
|
365 |
if ($verify == 1) {
|
366 |
$message_id = $this->set_client_message_id($message_id);
|
500 |
die('Error downloading file ' . $url);
|
501 |
return $file_name;
|
502 |
}
|
|
|
|
|
|
|
|
|
|
|
503 |
}
|
504 |
?>
|
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.0.
|
8 |
Author URI: http://www.revmakx.com
|
9 |
*/
|
10 |
/************************************************************
|
@@ -26,7 +26,8 @@ Author URI: http://www.revmakx.com
|
|
26 |
**************************************************************/
|
27 |
|
28 |
if(!defined('IWP_MMB_CLIENT_VERSION'))
|
29 |
-
define('IWP_MMB_CLIENT_VERSION', '1.0.
|
|
|
30 |
|
31 |
if ( !defined('IWP_MMB_XFRAME_COOKIE')){
|
32 |
$siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
|
@@ -46,6 +47,7 @@ require_once("$iwp_mmb_plugin_dir/core.class.php");
|
|
46 |
require_once("$iwp_mmb_plugin_dir/stats.class.php");
|
47 |
require_once("$iwp_mmb_plugin_dir/backup.class.php");
|
48 |
require_once("$iwp_mmb_plugin_dir/installer.class.php");
|
|
|
49 |
require_once("$iwp_mmb_plugin_dir/api.php");
|
50 |
require_once("$iwp_mmb_plugin_dir/plugins/search/search.php");
|
51 |
require_once("$iwp_mmb_plugin_dir/plugins/cleanup/cleanup.php");
|
@@ -133,12 +135,15 @@ if( !function_exists ('iwp_mmb_parse_request')) {
|
|
133 |
}
|
134 |
|
135 |
if(isset($params['secure'])){
|
|
|
136 |
if($decrypted = $iwp_mmb_core->_secure_data($params['secure'])){
|
137 |
$decrypted = maybe_unserialize($decrypted);
|
138 |
if(is_array($decrypted)){
|
|
|
139 |
foreach($decrypted as $key => $val){
|
140 |
if(!is_numeric($key))
|
141 |
$params[$key] = $val;
|
|
|
142 |
}
|
143 |
unset($params['secure']);
|
144 |
} else $params['secure'] = $decrypted;
|
@@ -199,7 +204,7 @@ if( !function_exists ( 'iwp_mmb_add_site' )) {
|
|
199 |
return;
|
200 |
}
|
201 |
|
202 |
-
if (
|
203 |
$verify = openssl_verify($action . $id, base64_decode($signature), $public_key);
|
204 |
if ($verify == 1) {
|
205 |
$iwp_mmb_core->set_admin_panel_public_key($public_key);
|
@@ -341,6 +346,19 @@ if( !function_exists ( 'iwp_mmb_run_task_now' )) {
|
|
341 |
}
|
342 |
}
|
343 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
if( !function_exists ( 'iwp_mmb_check_backup_compat' )) {
|
345 |
function iwp_mmb_check_backup_compat($params)
|
346 |
{
|
@@ -420,6 +438,18 @@ if( !function_exists ( 'iwp_mmb_restore_now' )) {
|
|
420 |
}
|
421 |
|
422 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
423 |
|
424 |
|
425 |
if( !function_exists ( 'iwp_mmb_clean_orphan_backups' )) {
|
@@ -679,6 +709,26 @@ if( !function_exists('iwp_mmb_plugin_actions') ){
|
|
679 |
}
|
680 |
}
|
681 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
682 |
$iwp_mmb_core = new IWP_MMB_Core();
|
683 |
|
684 |
if(isset($_GET['auto_login']))
|
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.0.4
|
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.0.4');
|
30 |
+
|
31 |
|
32 |
if ( !defined('IWP_MMB_XFRAME_COOKIE')){
|
33 |
$siteurl = function_exists('get_site_option') ? get_site_option( 'siteurl' ) : get_option('siteurl');
|
47 |
require_once("$iwp_mmb_plugin_dir/stats.class.php");
|
48 |
require_once("$iwp_mmb_plugin_dir/backup.class.php");
|
49 |
require_once("$iwp_mmb_plugin_dir/installer.class.php");
|
50 |
+
require_once("$iwp_mmb_plugin_dir/addons/backup_repository/backup_repository.class.php");
|
51 |
require_once("$iwp_mmb_plugin_dir/api.php");
|
52 |
require_once("$iwp_mmb_plugin_dir/plugins/search/search.php");
|
53 |
require_once("$iwp_mmb_plugin_dir/plugins/cleanup/cleanup.php");
|
135 |
}
|
136 |
|
137 |
if(isset($params['secure'])){
|
138 |
+
|
139 |
if($decrypted = $iwp_mmb_core->_secure_data($params['secure'])){
|
140 |
$decrypted = maybe_unserialize($decrypted);
|
141 |
if(is_array($decrypted)){
|
142 |
+
|
143 |
foreach($decrypted as $key => $val){
|
144 |
if(!is_numeric($key))
|
145 |
$params[$key] = $val;
|
146 |
+
|
147 |
}
|
148 |
unset($params['secure']);
|
149 |
} else $params['secure'] = $decrypted;
|
204 |
return;
|
205 |
}
|
206 |
|
207 |
+
if (checkOpenSSL() && !$user_random_key_signing) {
|
208 |
$verify = openssl_verify($action . $id, base64_decode($signature), $public_key);
|
209 |
if ($verify == 1) {
|
210 |
$iwp_mmb_core->set_admin_panel_public_key($public_key);
|
346 |
}
|
347 |
}
|
348 |
|
349 |
+
if( !function_exists ( 'iwp_mmb_delete_task_now' )) {
|
350 |
+
function iwp_mmb_delete_task_now($params)
|
351 |
+
{
|
352 |
+
global $iwp_mmb_core;
|
353 |
+
$iwp_mmb_core->get_backup_instance();
|
354 |
+
$return = $iwp_mmb_core->backup_instance->delete_task_now($params['task_name']);
|
355 |
+
if (is_array($return) && array_key_exists('error', $return))
|
356 |
+
iwp_mmb_response($return['error'], false);
|
357 |
+
else {
|
358 |
+
iwp_mmb_response($return, true);
|
359 |
+
}
|
360 |
+
}
|
361 |
+
}
|
362 |
if( !function_exists ( 'iwp_mmb_check_backup_compat' )) {
|
363 |
function iwp_mmb_check_backup_compat($params)
|
364 |
{
|
438 |
}
|
439 |
|
440 |
|
441 |
+
if( !function_exists ( 'iwp_mmb_backup_repository' )) {
|
442 |
+
function iwp_mmb_backup_repository($params)
|
443 |
+
{
|
444 |
+
global $iwp_mmb_core;
|
445 |
+
$iwp_mmb_core->get_backup_repository_instance();
|
446 |
+
$return = $iwp_mmb_core->backup_repository_instance->backup_repository($params);
|
447 |
+
if (is_array($return) && array_key_exists('error', $return))
|
448 |
+
iwp_mmb_response($return['error'], false);
|
449 |
+
else
|
450 |
+
iwp_mmb_response($return, true);
|
451 |
+
}
|
452 |
+
}
|
453 |
|
454 |
|
455 |
if( !function_exists ( 'iwp_mmb_clean_orphan_backups' )) {
|
709 |
}
|
710 |
}
|
711 |
|
712 |
+
if(!function_exists('checkOpenSSL')){
|
713 |
+
function checkOpenSSL(){
|
714 |
+
if(!function_exists('openssl_verify')){
|
715 |
+
return false;
|
716 |
+
}
|
717 |
+
else{
|
718 |
+
$key = @openssl_pkey_new();
|
719 |
+
@openssl_pkey_export($key, $privateKey);
|
720 |
+
$privateKey = base64_encode($privateKey);
|
721 |
+
$publicKey = @openssl_pkey_get_details($key);
|
722 |
+
$publicKey = $publicKey["key"];
|
723 |
+
|
724 |
+
if(empty($publicKey) || empty($privateKey)){
|
725 |
+
return false;
|
726 |
+
}
|
727 |
+
}
|
728 |
+
return true;
|
729 |
+
}
|
730 |
+
}
|
731 |
+
|
732 |
$iwp_mmb_core = new IWP_MMB_Core();
|
733 |
|
734 |
if(isset($_GET['auto_login']))
|
installer.class.php
CHANGED
@@ -489,43 +489,96 @@ class IWP_MMB_Installer extends IWP_MMB_Core
|
|
489 |
|
490 |
$upgrader = false;
|
491 |
$pr_update = array();
|
|
|
|
|
492 |
$result = array();
|
493 |
$premium_update = array();
|
494 |
-
$premium_update = apply_filters('
|
495 |
-
|
496 |
if (!empty($premium_update)) {
|
|
|
497 |
foreach ($premium as $pr) {
|
498 |
-
|
499 |
$update = array_change_key_case($update, CASE_LOWER);
|
500 |
-
|
501 |
if ($update['name'] == $pr['name']) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
502 |
$update_result = false;
|
503 |
if (isset($update['url'])) {
|
504 |
if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
|
505 |
$pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
|
506 |
|
507 |
-
if ($upgrader == false) {
|
508 |
$upgrader_skin = new WP_Upgrader_Skin();
|
509 |
$upgrader_skin->done_header = true;
|
510 |
-
|
511 |
$upgrader = new WP_Upgrader();
|
512 |
-
}
|
513 |
-
|
514 |
@$update_result = $upgrader->run(array(
|
515 |
'package' => $update['url'],
|
516 |
'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
|
517 |
'clear_destination' => true,
|
518 |
'clear_working' => true,
|
|
|
519 |
'hook_extra' => array()
|
520 |
));
|
521 |
$update_result = !$update_result || is_wp_error($update_result) ? $this->iwp_mmb_get_error($update_result) : 1;
|
522 |
|
523 |
} else if (isset($update['callback'])) {
|
524 |
if (is_array($update['callback'])) {
|
525 |
-
$update_result = call_user_func(array(
|
526 |
-
$update['callback'][0],
|
527 |
-
$update['callback'][1]
|
528 |
-
));
|
529 |
} else if (is_string($update['callback'])) {
|
530 |
$update_result = call_user_func($update['callback']);
|
531 |
} else {
|
@@ -539,7 +592,6 @@ class IWP_MMB_Installer extends IWP_MMB_Core
|
|
539 |
$pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
|
540 |
}
|
541 |
}
|
542 |
-
}
|
543 |
return $pr_update;
|
544 |
} else {
|
545 |
foreach ($premium as $pr) {
|
@@ -653,12 +705,14 @@ class IWP_MMB_Installer extends IWP_MMB_Core
|
|
653 |
if (in_array($path, $activated_plugins)) {
|
654 |
$plugins['active'][$br_a]['path'] = $path;
|
655 |
$plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
|
|
|
656 |
$br_a++;
|
657 |
}
|
658 |
|
659 |
if (!in_array($path, $activated_plugins)) {
|
660 |
$plugins['inactive'][$br_i]['path'] = $path;
|
661 |
$plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
|
|
|
662 |
$br_i++;
|
663 |
}
|
664 |
|
@@ -708,6 +762,7 @@ class IWP_MMB_Installer extends IWP_MMB_Core
|
|
708 |
if ($current_theme == $theme_name) {
|
709 |
$themes['active'][$br_a]['path'] = $theme['Template'];
|
710 |
$themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
|
|
|
711 |
$themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
|
712 |
$br_a++;
|
713 |
}
|
@@ -715,6 +770,7 @@ class IWP_MMB_Installer extends IWP_MMB_Core
|
|
715 |
if ($current_theme != $theme_name) {
|
716 |
$themes['inactive'][$br_i]['path'] = $theme['Template'];
|
717 |
$themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
|
|
|
718 |
$themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
|
719 |
$br_i++;
|
720 |
}
|
489 |
|
490 |
$upgrader = false;
|
491 |
$pr_update = array();
|
492 |
+
$themes = array();
|
493 |
+
$plugins = array();
|
494 |
$result = array();
|
495 |
$premium_update = array();
|
496 |
+
$premium_update = apply_filters('mwp_premium_perform_update', $premium_update);
|
|
|
497 |
if (!empty($premium_update)) {
|
498 |
+
|
499 |
foreach ($premium as $pr) {
|
500 |
+
foreach ($premium_update as $key => $update) {
|
501 |
$update = array_change_key_case($update, CASE_LOWER);
|
|
|
502 |
if ($update['name'] == $pr['name']) {
|
503 |
+
|
504 |
+
// prepare bulk updates for premiums that use WordPress upgrader
|
505 |
+
if(isset($update['type'])){
|
506 |
+
if($update['type'] == 'plugin'){
|
507 |
+
if(isset($update['slug']) && !empty($update['slug']))
|
508 |
+
$plugins[$update['slug']] = $update;
|
509 |
+
}
|
510 |
+
|
511 |
+
if($update['type'] == 'theme'){
|
512 |
+
if(isset($update['template']) && !empty($update['template']))
|
513 |
+
$themes[$update['template']] = $update;
|
514 |
+
}
|
515 |
+
}
|
516 |
+
} else {
|
517 |
+
unset($premium_update[$key]);
|
518 |
+
}
|
519 |
+
}
|
520 |
+
}
|
521 |
+
|
522 |
+
// try default wordpress upgrader
|
523 |
+
if(!empty($plugins)){
|
524 |
+
$updateplugins = $this->upgrade_plugins(array_keys($plugins));
|
525 |
+
if(!empty($updateplugins) && isset($updateplugins['upgraded'])){
|
526 |
+
foreach ($premium_update as $key => $update) {
|
527 |
+
$update = array_change_key_case($update, CASE_LOWER);
|
528 |
+
foreach($updateplugins['upgraded'] as $slug => $upgrade){
|
529 |
+
if( isset($update['slug']) && $update['slug'] == $slug){
|
530 |
+
if( $upgrade == 1 )
|
531 |
+
unset($premium_update[$key]);
|
532 |
+
|
533 |
+
$pr_update['plugins']['upgraded'][md5($update['name'])] = $upgrade;
|
534 |
+
}
|
535 |
+
}
|
536 |
+
}
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
if(!empty($themes)){
|
541 |
+
$updatethemes = $this->upgrade_themes(array_keys($themes));
|
542 |
+
if(!empty($updatethemes) && isset($updatethemes['upgraded'])){
|
543 |
+
foreach ($premium_update as $key => $update) {
|
544 |
+
$update = array_change_key_case($update, CASE_LOWER);
|
545 |
+
foreach($updatethemes['upgraded'] as $template => $upgrade){
|
546 |
+
if( isset($update['template']) && $update['template'] == $template) {
|
547 |
+
if( $upgrade == 1 )
|
548 |
+
unset($premium_update[$key]);
|
549 |
+
|
550 |
+
$pr_update['themes']['upgraded'][md5($update['name'])] = $upgrade;
|
551 |
+
}
|
552 |
+
}
|
553 |
+
}
|
554 |
+
}
|
555 |
+
}
|
556 |
+
|
557 |
+
//try direct install with overwrite
|
558 |
+
if (!empty($premium_update)) {
|
559 |
+
foreach ($premium_update as $update) {
|
560 |
+
$update = array_change_key_case($update, CASE_LOWER);
|
561 |
$update_result = false;
|
562 |
if (isset($update['url'])) {
|
563 |
if (defined('WP_INSTALLING') && file_exists(ABSPATH . '.maintenance'))
|
564 |
$pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = 'Site under maintanace.';
|
565 |
|
|
|
566 |
$upgrader_skin = new WP_Upgrader_Skin();
|
567 |
$upgrader_skin->done_header = true;
|
|
|
568 |
$upgrader = new WP_Upgrader();
|
|
|
|
|
569 |
@$update_result = $upgrader->run(array(
|
570 |
'package' => $update['url'],
|
571 |
'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR . '/themes' : WP_PLUGIN_DIR,
|
572 |
'clear_destination' => true,
|
573 |
'clear_working' => true,
|
574 |
+
'is_multi' => true,
|
575 |
'hook_extra' => array()
|
576 |
));
|
577 |
$update_result = !$update_result || is_wp_error($update_result) ? $this->iwp_mmb_get_error($update_result) : 1;
|
578 |
|
579 |
} else if (isset($update['callback'])) {
|
580 |
if (is_array($update['callback'])) {
|
581 |
+
$update_result = call_user_func(array( $update['callback'][0], $update['callback'][1] ));
|
|
|
|
|
|
|
582 |
} else if (is_string($update['callback'])) {
|
583 |
$update_result = call_user_func($update['callback']);
|
584 |
} else {
|
592 |
$pr_update[$update['type'] . 's']['upgraded'][md5($update['name'])] = $update_result;
|
593 |
}
|
594 |
}
|
|
|
595 |
return $pr_update;
|
596 |
} else {
|
597 |
foreach ($premium as $pr) {
|
705 |
if (in_array($path, $activated_plugins)) {
|
706 |
$plugins['active'][$br_a]['path'] = $path;
|
707 |
$plugins['active'][$br_a]['name'] = strip_tags($plugin['Name']);
|
708 |
+
$plugins['active'][$br_a]['version'] = $plugin['Version'];
|
709 |
$br_a++;
|
710 |
}
|
711 |
|
712 |
if (!in_array($path, $activated_plugins)) {
|
713 |
$plugins['inactive'][$br_i]['path'] = $path;
|
714 |
$plugins['inactive'][$br_i]['name'] = strip_tags($plugin['Name']);
|
715 |
+
$plugins['inactive'][$br_i]['version'] = $plugin['Version'];
|
716 |
$br_i++;
|
717 |
}
|
718 |
|
762 |
if ($current_theme == $theme_name) {
|
763 |
$themes['active'][$br_a]['path'] = $theme['Template'];
|
764 |
$themes['active'][$br_a]['name'] = strip_tags($theme['Name']);
|
765 |
+
$themes['active'][$br_a]['version'] = $theme['Version'];
|
766 |
$themes['active'][$br_a]['stylesheet'] = $theme['Stylesheet'];
|
767 |
$br_a++;
|
768 |
}
|
770 |
if ($current_theme != $theme_name) {
|
771 |
$themes['inactive'][$br_i]['path'] = $theme['Template'];
|
772 |
$themes['inactive'][$br_i]['name'] = strip_tags($theme['Name']);
|
773 |
+
$themes['inactive'][$br_i]['version'] = $theme['Version'];
|
774 |
$themes['inactive'][$br_i]['stylesheet'] = $theme['Stylesheet'];
|
775 |
$br_i++;
|
776 |
}
|
lib/dropbox.oauth.php
ADDED
@@ -0,0 +1,1133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Dropbox class
|
5 |
+
*
|
6 |
+
* This source file can be used to communicate with Dropbox (http://dropbox.com)
|
7 |
+
*
|
8 |
+
* The class is documented in the file itself. If you find any bugs help me out and report them. Reporting can be done by sending an email to php-dropbox-bugs[at]verkoyen[dot]eu.
|
9 |
+
* If you report a bug, make sure you give me enough information (include your code).
|
10 |
+
*
|
11 |
+
* Changelog since 1.0.4
|
12 |
+
* - Fixed filesPost so it returns a boolean.
|
13 |
+
* - Some code styling
|
14 |
+
*
|
15 |
+
* Changelog since 1.0.3
|
16 |
+
* - Corrected the authorize-URL (thx to Jacob Budin).
|
17 |
+
*
|
18 |
+
* Changelog since 1.0.2
|
19 |
+
* - Added methods to enable oauth-usage.
|
20 |
+
*
|
21 |
+
* Changelog since 1.0.1
|
22 |
+
* - Bugfix: when doing multiple calles where GET and POST is mixed, the postfields should be reset (thx to Daniel Hトてスsken)
|
23 |
+
*
|
24 |
+
* Changelog since 1.0.0
|
25 |
+
* - fixed some issues with generation off the basestring
|
26 |
+
*
|
27 |
+
* License
|
28 |
+
* Copyright (c), Tijs Verkoyen. All rights reserved.
|
29 |
+
*
|
30 |
+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
31 |
+
*
|
32 |
+
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
33 |
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
34 |
+
* 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
|
35 |
+
*
|
36 |
+
* This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
|
37 |
+
*
|
38 |
+
* @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
|
39 |
+
* @version 1.0.5
|
40 |
+
*
|
41 |
+
* @copyright Copyright (c), Tijs Verkoyen. All rights reserved.
|
42 |
+
* @license BSD License
|
43 |
+
*/
|
44 |
+
class Dropbox
|
45 |
+
{
|
46 |
+
// internal constant to enable/disable debugging
|
47 |
+
const DEBUG = false;
|
48 |
+
|
49 |
+
// url for the dropbox-api
|
50 |
+
const API_URL = 'https://api.dropbox.com';
|
51 |
+
const API_AUTH_URL = 'https://www.dropbox.com';
|
52 |
+
const API_CONTENT_URL = 'https://api-content.dropbox.com';
|
53 |
+
|
54 |
+
// port for the dropbox-api
|
55 |
+
const API_PORT = 443;
|
56 |
+
|
57 |
+
// current version
|
58 |
+
const VERSION = '1.0.5';
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* A cURL instance
|
63 |
+
*
|
64 |
+
* @var resource
|
65 |
+
*/
|
66 |
+
private $curl;
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* The application key
|
71 |
+
*
|
72 |
+
* @var string
|
73 |
+
*/
|
74 |
+
private $applicationKey;
|
75 |
+
|
76 |
+
|
77 |
+
/**
|
78 |
+
* The application secret
|
79 |
+
*
|
80 |
+
* @var string
|
81 |
+
*/
|
82 |
+
private $applicationSecret;
|
83 |
+
|
84 |
+
|
85 |
+
/**
|
86 |
+
* The oAuth-token
|
87 |
+
*
|
88 |
+
* @var string
|
89 |
+
*/
|
90 |
+
private $oAuthToken = '';
|
91 |
+
|
92 |
+
|
93 |
+
/**
|
94 |
+
* The oAuth-token-secret
|
95 |
+
*
|
96 |
+
* @var string
|
97 |
+
*/
|
98 |
+
private $oAuthTokenSecret = '';
|
99 |
+
|
100 |
+
|
101 |
+
/**
|
102 |
+
* The timeout
|
103 |
+
*
|
104 |
+
* @var int
|
105 |
+
*/
|
106 |
+
private $timeOut = 1200;
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* The user agent
|
111 |
+
*
|
112 |
+
* @var string
|
113 |
+
*/
|
114 |
+
private $userAgent;
|
115 |
+
|
116 |
+
|
117 |
+
// class methods
|
118 |
+
/**
|
119 |
+
* Default constructor
|
120 |
+
*
|
121 |
+
* @return void
|
122 |
+
* @param string $applicationKey The application key to use.
|
123 |
+
* @param string $applicationSecret The application secret to use.
|
124 |
+
*/
|
125 |
+
public function __construct($applicationKey, $applicationSecret)
|
126 |
+
{
|
127 |
+
$this->setApplicationKey($applicationKey);
|
128 |
+
$this->setApplicationSecret($applicationSecret);
|
129 |
+
}
|
130 |
+
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Default destructor
|
134 |
+
*
|
135 |
+
* @return void
|
136 |
+
*/
|
137 |
+
public function __destruct()
|
138 |
+
{
|
139 |
+
if($this->curl != null) curl_close($this->curl);
|
140 |
+
}
|
141 |
+
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Format the parameters as a querystring
|
145 |
+
*
|
146 |
+
* @return string
|
147 |
+
* @param array $parameters The parameters to pass.
|
148 |
+
*/
|
149 |
+
private function buildQuery(array $parameters)
|
150 |
+
{
|
151 |
+
// no parameters?
|
152 |
+
if(empty($parameters)) return '';
|
153 |
+
|
154 |
+
// encode the keys
|
155 |
+
$keys = self::urlencode_rfc3986(array_keys($parameters));
|
156 |
+
|
157 |
+
// encode the values
|
158 |
+
$values = self::urlencode_rfc3986(array_values($parameters));
|
159 |
+
|
160 |
+
// reset the parameters
|
161 |
+
$parameters = array_combine($keys, $values);
|
162 |
+
|
163 |
+
// sort parameters by key
|
164 |
+
uksort($parameters, 'strcmp');
|
165 |
+
|
166 |
+
// loop parameters
|
167 |
+
foreach($parameters as $key => $value)
|
168 |
+
{
|
169 |
+
// sort by value
|
170 |
+
if(is_array($value)) $parameters[$key] = natsort($value);
|
171 |
+
}
|
172 |
+
|
173 |
+
// process parameters
|
174 |
+
foreach($parameters as $key => $value) $chunks[] = $key . '=' . str_replace('%25', '%', $value);
|
175 |
+
|
176 |
+
// return
|
177 |
+
return implode('&', $chunks);
|
178 |
+
}
|
179 |
+
|
180 |
+
|
181 |
+
/**
|
182 |
+
* All OAuth 1.0 requests use the same basic algorithm for creating a signature base string and a signature.
|
183 |
+
* The signature base string is composed of the HTTP method being used, followed by an ampersand ("&") and then the URL-encoded base URL being accessed,
|
184 |
+
* complete with path (but not query parameters), followed by an ampersand ("&").
|
185 |
+
* Then, you take all query parameters and POST body parameters (when the POST body is of the URL-encoded type, otherwise the POST body is ignored),
|
186 |
+
* including the OAuth parameters necessary for negotiation with the request at hand, and sort them in lexicographical order by first parameter name and
|
187 |
+
* then parameter value (for duplicate parameters), all the while ensuring that both the key and the value for each parameter are URL encoded in isolation.
|
188 |
+
* Instead of using the equals ("=") sign to mark the key/value relationship, you use the URL-encoded form of "%3D". Each parameter is then joined by the
|
189 |
+
* URL-escaped ampersand sign, "%26".
|
190 |
+
*
|
191 |
+
* @return string
|
192 |
+
* @param string $url The url to use.
|
193 |
+
* @param string $method The method that will be called.
|
194 |
+
* @param array $parameters The parameters to pass.
|
195 |
+
*/
|
196 |
+
private function calculateBaseString($url, $method, array $parameters)
|
197 |
+
{
|
198 |
+
// redefine
|
199 |
+
$url = (string) $url;
|
200 |
+
$parameters = (array) $parameters;
|
201 |
+
|
202 |
+
// init var
|
203 |
+
$pairs = array();
|
204 |
+
$chunks = array();
|
205 |
+
|
206 |
+
// sort parameters by key
|
207 |
+
uksort($parameters, 'strcmp');
|
208 |
+
|
209 |
+
// loop parameters
|
210 |
+
foreach($parameters as $key => $value)
|
211 |
+
{
|
212 |
+
// sort by value
|
213 |
+
if(is_array($value)) $parameters[$key] = natsort($value);
|
214 |
+
}
|
215 |
+
|
216 |
+
// process queries
|
217 |
+
foreach($parameters as $key => $value)
|
218 |
+
{
|
219 |
+
// only add if not already in the url
|
220 |
+
if(substr_count($url, $key . '=' . $value) == 0) $chunks[] = self::urlencode_rfc3986($key) . '%3D' . self::urlencode_rfc3986($value);
|
221 |
+
}
|
222 |
+
|
223 |
+
$urlChunks = explode('/', $url);
|
224 |
+
$i = 0;
|
225 |
+
|
226 |
+
foreach($urlChunks as &$chunk)
|
227 |
+
{
|
228 |
+
if($i > 4) $chunk = self::urlencode_rfc3986($chunk);
|
229 |
+
else $chunk = urlencode($chunk);
|
230 |
+
|
231 |
+
$i++;
|
232 |
+
|
233 |
+
}
|
234 |
+
|
235 |
+
// build base
|
236 |
+
$base = $method . '&';
|
237 |
+
$base .= implode('%2F', $urlChunks);
|
238 |
+
$base .= (substr_count($url, '?')) ? '%26' : '&';
|
239 |
+
$base .= implode('%26', $chunks);
|
240 |
+
$base = str_replace(array('%3F', '%20'), array('&', '%2520'), $base);
|
241 |
+
|
242 |
+
// return
|
243 |
+
return $base;
|
244 |
+
}
|
245 |
+
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Build the Authorization header
|
249 |
+
* @later: fix me
|
250 |
+
*
|
251 |
+
* @return string
|
252 |
+
* @param array $parameters The parameters to pass.
|
253 |
+
* @param string $url The url to use.
|
254 |
+
*/
|
255 |
+
private function calculateHeader(array $parameters, $url)
|
256 |
+
{
|
257 |
+
// redefine
|
258 |
+
$url = (string) $url;
|
259 |
+
|
260 |
+
// divide into parts
|
261 |
+
$parts = parse_url($url);
|
262 |
+
|
263 |
+
// init var
|
264 |
+
$chunks = array();
|
265 |
+
|
266 |
+
// process queries
|
267 |
+
foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', self::urlencode_rfc3986($key) . '="' . self::urlencode_rfc3986($value) . '"');
|
268 |
+
$parts['path']=str_replace("%2F", "/", rawurlencode($parts['path']));
|
269 |
+
// build return
|
270 |
+
$return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
|
271 |
+
$return .= implode(',', $chunks);
|
272 |
+
// prepend name and OAuth part
|
273 |
+
return $return;
|
274 |
+
}
|
275 |
+
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Make an call to the oAuth
|
279 |
+
* @todo refactor me
|
280 |
+
*
|
281 |
+
* @return array
|
282 |
+
* @param string $url The url that has to be called.
|
283 |
+
* @param array[optional] $parameters The parameters to pass.
|
284 |
+
* @param string[optional] $method Which HTTP-method should we use? Possible values are POST, GET.
|
285 |
+
* @param bool[optional] $expectJSON Do we expect JSON?
|
286 |
+
*/
|
287 |
+
private function doOAuthCall($url, array $parameters = null, $method = 'POST', $expectJSON = true)
|
288 |
+
{
|
289 |
+
// redefine
|
290 |
+
$url = (string) $url;
|
291 |
+
|
292 |
+
// append default parameters
|
293 |
+
$parameters['oauth_consumer_key'] = $this->getApplicationKey();
|
294 |
+
$parameters['oauth_nonce'] = md5(microtime() . rand());
|
295 |
+
$parameters['oauth_timestamp'] = time();
|
296 |
+
$parameters['oauth_signature_method'] = 'HMAC-SHA1';
|
297 |
+
$parameters['oauth_version'] = '1.0';
|
298 |
+
|
299 |
+
// calculate the base string
|
300 |
+
$base = $this->calculateBaseString(self::API_URL . '/' . $url, 'POST', $parameters);
|
301 |
+
|
302 |
+
// add sign into the parameters
|
303 |
+
$parameters['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
|
304 |
+
|
305 |
+
// calculate header
|
306 |
+
$header = $this->calculateHeader($parameters, self::API_URL . '/' . $url);
|
307 |
+
|
308 |
+
if($method == 'POST')
|
309 |
+
{
|
310 |
+
$options[CURLOPT_POST] = true;
|
311 |
+
$options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
|
312 |
+
}
|
313 |
+
|
314 |
+
else
|
315 |
+
{
|
316 |
+
// reset post
|
317 |
+
$options[CURLOPT_POST] = 0;
|
318 |
+
unset($options[CURLOPT_POSTFIELDS]);
|
319 |
+
|
320 |
+
// add the parameters into the querystring
|
321 |
+
if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
|
322 |
+
}
|
323 |
+
|
324 |
+
// set options
|
325 |
+
$options[CURLOPT_URL] = self::API_URL . '/' . $url;
|
326 |
+
$options[CURLOPT_PORT] = self::API_PORT;
|
327 |
+
$options[CURLOPT_USERAGENT] = $this->getUserAgent();
|
328 |
+
if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
|
329 |
+
$options[CURLOPT_RETURNTRANSFER] = true;
|
330 |
+
$options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
|
331 |
+
$options[CURLOPT_SSL_VERIFYPEER] = false;
|
332 |
+
$options[CURLOPT_SSL_VERIFYHOST] = false;
|
333 |
+
$options[CURLOPT_HTTPHEADER] = array('Expect:');
|
334 |
+
|
335 |
+
// init
|
336 |
+
$this->curl = curl_init();
|
337 |
+
|
338 |
+
// set options
|
339 |
+
curl_setopt_array($this->curl, $options);
|
340 |
+
|
341 |
+
// execute
|
342 |
+
$response = curl_exec($this->curl);
|
343 |
+
$headers = curl_getinfo($this->curl);
|
344 |
+
|
345 |
+
// fetch errors
|
346 |
+
$errorNumber = curl_errno($this->curl);
|
347 |
+
$errorMessage = curl_error($this->curl);
|
348 |
+
|
349 |
+
// error?
|
350 |
+
if($errorNumber != '') throw new DropboxException($errorMessage, $errorNumber);
|
351 |
+
|
352 |
+
// return
|
353 |
+
if($expectJSON) return json_decode($response, true);
|
354 |
+
|
355 |
+
// fallback
|
356 |
+
return $response;
|
357 |
+
}
|
358 |
+
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Make the call
|
362 |
+
*
|
363 |
+
* @return string
|
364 |
+
* @param string $url The url to call.
|
365 |
+
* @param array[optional] $parameters Optional parameters.
|
366 |
+
* @param bool[optional] $method The method to use. Possible values are GET, POST.
|
367 |
+
* @param string[optional] $filePath The path to the file to upload.
|
368 |
+
* @param bool[optional] $expectJSON Do we expect JSON?
|
369 |
+
* @param bool[optional] $isContent Is this content?
|
370 |
+
*/
|
371 |
+
private function doCall($url, array $parameters = null, $method = 'GET', $filePath = null, $expectJSON = true, $isContent = false)
|
372 |
+
{
|
373 |
+
// allowed methods
|
374 |
+
$allowedMethods = array('GET', 'POST');
|
375 |
+
|
376 |
+
// redefine
|
377 |
+
$url = (string) $url;
|
378 |
+
$parameters = (array) $parameters;
|
379 |
+
$method = (string) $method;
|
380 |
+
$expectJSON = (bool) $expectJSON;
|
381 |
+
|
382 |
+
// validate method
|
383 |
+
if(!in_array($method, $allowedMethods)) throw new DropboxException('Unknown method (' . $method . '). Allowed methods are: ' . implode(', ', $allowedMethods));
|
384 |
+
|
385 |
+
// append default parameters
|
386 |
+
$oauth['oauth_consumer_key'] = $this->getApplicationKey();
|
387 |
+
$oauth['oauth_nonce'] = md5(microtime() . rand());
|
388 |
+
$oauth['oauth_timestamp'] = time();
|
389 |
+
$oauth['oauth_token'] = $this->getOAuthToken();
|
390 |
+
$oauth['oauth_signature_method'] = 'HMAC-SHA1';
|
391 |
+
$oauth['oauth_version'] = '1.0';
|
392 |
+
|
393 |
+
// set data
|
394 |
+
$data = $oauth;
|
395 |
+
if(!empty($parameters))
|
396 |
+
{
|
397 |
+
// convert to UTF-8
|
398 |
+
foreach($parameters as &$value) $value = utf8_encode($value);
|
399 |
+
|
400 |
+
// merge
|
401 |
+
$data = array_merge($data, $parameters);
|
402 |
+
}
|
403 |
+
|
404 |
+
if($filePath != null)
|
405 |
+
{
|
406 |
+
// process file
|
407 |
+
$fileInfo = pathinfo($filePath);
|
408 |
+
|
409 |
+
// add to the data
|
410 |
+
$data['file'] = $fileInfo['basename'];
|
411 |
+
|
412 |
+
}
|
413 |
+
|
414 |
+
// calculate the base string
|
415 |
+
if($isContent) $base = $this->calculateBaseString(self::API_CONTENT_URL . '/' . $url, $method, $data);
|
416 |
+
else $base = $this->calculateBaseString(self::API_URL . '/' . $url, $method, $data);
|
417 |
+
|
418 |
+
// based on the method, we should handle the parameters in a different way
|
419 |
+
if($method == 'POST')
|
420 |
+
{
|
421 |
+
// file provided?
|
422 |
+
if($filePath != null)
|
423 |
+
{
|
424 |
+
// build a boundary
|
425 |
+
$boundary = md5(time());
|
426 |
+
|
427 |
+
// init var
|
428 |
+
$content = '--' . $boundary . "\r\n";
|
429 |
+
|
430 |
+
// set file
|
431 |
+
$content .= 'Content-Disposition: form-data; name=file; filename="' . $fileInfo['basename'] . '"' . "\r\n";
|
432 |
+
$content .= 'Content-Type: application/octet-stream' . "\r\n";
|
433 |
+
$content .= "\r\n";
|
434 |
+
$content .= file_get_contents($filePath);
|
435 |
+
$content .= "\r\n";
|
436 |
+
$content .= "--" . $boundary . '--';
|
437 |
+
|
438 |
+
// build headers
|
439 |
+
$headers[] = 'Content-Type: multipart/form-data; boundary=' . $boundary;
|
440 |
+
$headers[] = 'Content-Length: ' . strlen($content);
|
441 |
+
|
442 |
+
// set content
|
443 |
+
$options[CURLOPT_POSTFIELDS] = $content;
|
444 |
+
}
|
445 |
+
|
446 |
+
// no file
|
447 |
+
else $options[CURLOPT_POSTFIELDS] = $this->buildQuery($parameters);
|
448 |
+
|
449 |
+
// enable post
|
450 |
+
$options[CURLOPT_POST] = 1;
|
451 |
+
}
|
452 |
+
|
453 |
+
else
|
454 |
+
{
|
455 |
+
// reset post
|
456 |
+
$options[CURLOPT_POST] = 0;
|
457 |
+
unset($options[CURLOPT_POSTFIELDS]);
|
458 |
+
$url=str_replace("%2F", "/", rawurlencode($url));
|
459 |
+
|
460 |
+
// add the parameters into the querystring
|
461 |
+
if(!empty($parameters)) $url .= '?' . $this->buildQuery($parameters);
|
462 |
+
}
|
463 |
+
|
464 |
+
// add sign into the parameters
|
465 |
+
$oauth['oauth_signature'] = $this->hmacsha1($this->getApplicationSecret() . '&' . $this->getOAuthTokenSecret(), $base);
|
466 |
+
|
467 |
+
if($isContent) $headers[] = $this->calculateHeader($oauth, self::API_CONTENT_URL . '/' . $url);
|
468 |
+
else $headers[] = $this->calculateHeader($oauth, self::API_URL . '/' . $url);
|
469 |
+
$headers[] = 'Expect:';
|
470 |
+
|
471 |
+
// set options
|
472 |
+
if($isContent) $options[CURLOPT_URL] = self::API_CONTENT_URL . '/' . $url;
|
473 |
+
else $options[CURLOPT_URL] = self::API_URL . '/' . $url;
|
474 |
+
$options[CURLOPT_PORT] = self::API_PORT;
|
475 |
+
$options[CURLOPT_USERAGENT] = $this->getUserAgent();
|
476 |
+
if(ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) $options[CURLOPT_FOLLOWLOCATION] = true;
|
477 |
+
$options[CURLOPT_RETURNTRANSFER] = true;
|
478 |
+
$options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
|
479 |
+
$options[CURLOPT_SSL_VERIFYPEER] = false;
|
480 |
+
$options[CURLOPT_SSL_VERIFYHOST] = false;
|
481 |
+
$options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
482 |
+
$options[CURLOPT_HTTPHEADER] = $headers;
|
483 |
+
// init
|
484 |
+
if($this->curl == null) $this->curl = curl_init();
|
485 |
+
|
486 |
+
// set options
|
487 |
+
curl_setopt_array($this->curl, $options);
|
488 |
+
|
489 |
+
// execute
|
490 |
+
$response = curl_exec($this->curl);
|
491 |
+
$headers = curl_getinfo($this->curl);
|
492 |
+
|
493 |
+
// fetch errors
|
494 |
+
$errorNumber = curl_errno($this->curl);
|
495 |
+
$errorMessage = curl_error($this->curl);
|
496 |
+
|
497 |
+
if(!$expectJSON && $isContent)
|
498 |
+
{
|
499 |
+
// is it JSON?
|
500 |
+
$json = @json_decode($response, true);
|
501 |
+
if($json !== false && isset($json['error'])) throw new DropboxException($json['error']);
|
502 |
+
|
503 |
+
// set return
|
504 |
+
$return['content_type'] = $headers['content_type'];
|
505 |
+
$return['data'] = base64_encode($response);
|
506 |
+
|
507 |
+
// return
|
508 |
+
return $return;
|
509 |
+
}
|
510 |
+
|
511 |
+
// we don't expect JSON, return the response
|
512 |
+
if(!$expectJSON) return $response;
|
513 |
+
|
514 |
+
// replace ids with their string values, added because of some PHP-version can't handle these large values
|
515 |
+
$response = preg_replace('/id":(\d+)/', 'id":"\1"', $response);
|
516 |
+
|
517 |
+
// we expect JSON, so decode it
|
518 |
+
$json = @json_decode($response, true);
|
519 |
+
|
520 |
+
// validate JSON
|
521 |
+
if($json === null)
|
522 |
+
{
|
523 |
+
// should we provide debug information
|
524 |
+
if(self::DEBUG)
|
525 |
+
{
|
526 |
+
// make it output proper
|
527 |
+
echo '<pre>';
|
528 |
+
|
529 |
+
// dump the header-information
|
530 |
+
var_dump($headers);
|
531 |
+
|
532 |
+
// dump the error
|
533 |
+
var_dump($errorMessage);
|
534 |
+
|
535 |
+
// dump the raw response
|
536 |
+
var_dump($response);
|
537 |
+
|
538 |
+
// end proper format
|
539 |
+
echo '</pre>';
|
540 |
+
}
|
541 |
+
|
542 |
+
// throw exception
|
543 |
+
throw new DropboxException('Invalid response.');
|
544 |
+
}
|
545 |
+
|
546 |
+
// any error
|
547 |
+
if(isset($json['error']))
|
548 |
+
{
|
549 |
+
// should we provide debug information
|
550 |
+
if(self::DEBUG)
|
551 |
+
{
|
552 |
+
// make it output proper
|
553 |
+
echo '<pre>';
|
554 |
+
|
555 |
+
// dump the header-information
|
556 |
+
var_dump($headers);
|
557 |
+
|
558 |
+
// dump the raw response
|
559 |
+
var_dump($response);
|
560 |
+
|
561 |
+
// end proper format
|
562 |
+
echo '</pre>';
|
563 |
+
}
|
564 |
+
|
565 |
+
if(isset($json['error']) && is_string($json['error'])) $message = $json['error'];
|
566 |
+
elseif(isset($json['error']['hash']) && $json['error']['hash'] != '') $message = (string) $json['error']['hash'];
|
567 |
+
else $message = 'Invalid response.';
|
568 |
+
|
569 |
+
// throw exception
|
570 |
+
throw new DropboxException($message);
|
571 |
+
}
|
572 |
+
|
573 |
+
// return
|
574 |
+
return $json;
|
575 |
+
}
|
576 |
+
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Get the application key
|
580 |
+
*
|
581 |
+
* @return string
|
582 |
+
*/
|
583 |
+
private function getApplicationKey()
|
584 |
+
{
|
585 |
+
return $this->applicationKey;
|
586 |
+
}
|
587 |
+
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Get the application secret
|
591 |
+
*
|
592 |
+
* @return string
|
593 |
+
*/
|
594 |
+
private function getApplicationSecret()
|
595 |
+
{
|
596 |
+
return $this->applicationSecret;
|
597 |
+
}
|
598 |
+
|
599 |
+
|
600 |
+
/**
|
601 |
+
* Get the oAuth-token
|
602 |
+
*
|
603 |
+
* @return string
|
604 |
+
*/
|
605 |
+
private function getOAuthToken()
|
606 |
+
{
|
607 |
+
return $this->oAuthToken;
|
608 |
+
}
|
609 |
+
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Get the oAuth-token-secret
|
613 |
+
*
|
614 |
+
* @return string
|
615 |
+
*/
|
616 |
+
private function getOAuthTokenSecret()
|
617 |
+
{
|
618 |
+
return $this->oAuthTokenSecret;
|
619 |
+
}
|
620 |
+
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Get the timeout
|
624 |
+
*
|
625 |
+
* @return int
|
626 |
+
*/
|
627 |
+
public function getTimeOut()
|
628 |
+
{
|
629 |
+
return (int) $this->timeOut;
|
630 |
+
}
|
631 |
+
|
632 |
+
|
633 |
+
/**
|
634 |
+
* Get the useragent that will be used. Our version will be prepended to yours.
|
635 |
+
* It will look like: "PHP Dropbox/<version> <your-user-agent>"
|
636 |
+
*
|
637 |
+
* @return string
|
638 |
+
*/
|
639 |
+
public function getUserAgent()
|
640 |
+
{
|
641 |
+
return (string) 'PHP Dropbox/' . self::VERSION . ' ' . $this->userAgent;
|
642 |
+
}
|
643 |
+
|
644 |
+
|
645 |
+
/**
|
646 |
+
* Set the application key
|
647 |
+
*
|
648 |
+
* @return void
|
649 |
+
* @param string $key The application key to use.
|
650 |
+
*/
|
651 |
+
private function setApplicationKey($key)
|
652 |
+
{
|
653 |
+
$this->applicationKey = (string) $key;
|
654 |
+
}
|
655 |
+
|
656 |
+
|
657 |
+
/**
|
658 |
+
* Set the application secret
|
659 |
+
*
|
660 |
+
* @return void
|
661 |
+
* @param string $secret The application secret to use.
|
662 |
+
*/
|
663 |
+
private function setApplicationSecret($secret)
|
664 |
+
{
|
665 |
+
$this->applicationSecret = (string) $secret;
|
666 |
+
}
|
667 |
+
|
668 |
+
|
669 |
+
/**
|
670 |
+
* Set the oAuth-token
|
671 |
+
*
|
672 |
+
* @return void
|
673 |
+
* @param string $token The token to use.
|
674 |
+
*/
|
675 |
+
public function setOAuthToken($token)
|
676 |
+
{
|
677 |
+
$this->oAuthToken = (string) $token;
|
678 |
+
}
|
679 |
+
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Set the oAuth-secret
|
683 |
+
*
|
684 |
+
* @return void
|
685 |
+
* @param string $secret The secret to use.
|
686 |
+
*/
|
687 |
+
public function setOAuthTokenSecret($secret)
|
688 |
+
{
|
689 |
+
$this->oAuthTokenSecret = (string) $secret;
|
690 |
+
}
|
691 |
+
|
692 |
+
|
693 |
+
/**
|
694 |
+
* Set the timeout
|
695 |
+
*
|
696 |
+
* @return void
|
697 |
+
* @param int $seconds The timeout in seconds.
|
698 |
+
*/
|
699 |
+
public function setTimeOut($seconds)
|
700 |
+
{
|
701 |
+
$this->timeOut = (int) $seconds;
|
702 |
+
}
|
703 |
+
|
704 |
+
|
705 |
+
/**
|
706 |
+
* Get the useragent that will be used. Our version will be prepended to yours.
|
707 |
+
* It will look like: "PHP Dropbox/<version> <your-user-agent>"
|
708 |
+
*
|
709 |
+
* @return void
|
710 |
+
* @param string $userAgent Your user-agent, it should look like <app-name>/<app-version>.
|
711 |
+
*/
|
712 |
+
public function setUserAgent($userAgent)
|
713 |
+
{
|
714 |
+
$this->userAgent = (string) $userAgent;
|
715 |
+
}
|
716 |
+
|
717 |
+
|
718 |
+
/**
|
719 |
+
* Build the signature for the data
|
720 |
+
*
|
721 |
+
* @return string
|
722 |
+
* @param string $key The key to use for signing.
|
723 |
+
* @param string $data The data that has to be signed.
|
724 |
+
*/
|
725 |
+
private function hmacsha1($key, $data)
|
726 |
+
{
|
727 |
+
return base64_encode(hash_hmac('SHA1', $data, $key, true));
|
728 |
+
}
|
729 |
+
|
730 |
+
|
731 |
+
/**
|
732 |
+
* URL-encode method for internatl use
|
733 |
+
*
|
734 |
+
* @return string
|
735 |
+
* @param mixed $value The value to encode.
|
736 |
+
*/
|
737 |
+
private static function urlencode_rfc3986($value)
|
738 |
+
{
|
739 |
+
if(is_array($value)) return array_map(array('Dropbox', 'urlencode_rfc3986'), $value);
|
740 |
+
else
|
741 |
+
{
|
742 |
+
$search = array('+', ' ', '%7E', '%');
|
743 |
+
$replace = array('%20', '%20', '~', '%25');
|
744 |
+
|
745 |
+
return str_replace($search, $replace, rawurlencode($value));
|
746 |
+
}
|
747 |
+
}
|
748 |
+
|
749 |
+
|
750 |
+
// oauth resources
|
751 |
+
/**
|
752 |
+
* Call for obtaining an OAuth request token.
|
753 |
+
* Returns a request token and the corresponding request token secret. This token and secret cannot be used to sign requests for the /metadata and /file content API calls.
|
754 |
+
* Their only purpose is for signing a request to oauth/access_token once the user has gone through the application authorization steps provided by oauth/authorize.
|
755 |
+
*
|
756 |
+
* @return array
|
757 |
+
*/
|
758 |
+
public function oAuthRequestToken()
|
759 |
+
{
|
760 |
+
// make the call
|
761 |
+
$response = $this->doOAuthCall('1/oauth/request_token', null, 'POST', false);
|
762 |
+
|
763 |
+
// process response
|
764 |
+
$response = (array) explode('&', $response);
|
765 |
+
$return = array();
|
766 |
+
|
767 |
+
// loop chunks
|
768 |
+
foreach($response as $chunk)
|
769 |
+
{
|
770 |
+
// split again
|
771 |
+
$chunks = explode('=', $chunk, 2);
|
772 |
+
|
773 |
+
// store return
|
774 |
+
if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
|
775 |
+
}
|
776 |
+
|
777 |
+
// return
|
778 |
+
return $return;
|
779 |
+
}
|
780 |
+
|
781 |
+
|
782 |
+
/**
|
783 |
+
* Redirect the user to the oauth/authorize location so that Dropbox can authenticate the user and ask whether or not the user wants to authorize the application to access
|
784 |
+
* file metadata and content on its behalf. oauth/authorize is not an API call per se, because it does not have a return value, but rather directs the user to a page on
|
785 |
+
* api.dropbox.com where they are provided means to log in to Dropbox and grant authority to the application requesting it.
|
786 |
+
* The page served by oauth/authorize should be presented to the user through their web browser.
|
787 |
+
* Please note, without directing the user to a Dropbox-provided page via oauth/authorize, it is impossible for your application to use the request token it received
|
788 |
+
* via oauth/request_token to obtain an access token from oauth/access_token.
|
789 |
+
*
|
790 |
+
* @return void
|
791 |
+
* @param string $oauthToken The request token of the application requesting authority from a user.
|
792 |
+
* @param string[optional] $oauthCallback After the user authorizes an application, the user is redirected to the application-served URL provided by this parameter.
|
793 |
+
*/
|
794 |
+
public function oAuthAuthorize($oauthToken, $oauthCallback = null)
|
795 |
+
{
|
796 |
+
// build parameters
|
797 |
+
$parameters = array();
|
798 |
+
$parameters['oauth_token'] = (string) $oauthToken;
|
799 |
+
if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
|
800 |
+
|
801 |
+
// build url
|
802 |
+
$url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
|
803 |
+
|
804 |
+
// redirect
|
805 |
+
header('Location: ' . $url);
|
806 |
+
exit;
|
807 |
+
}
|
808 |
+
|
809 |
+
public function mwp_oAuthAuthorize($oauthToken, $oauthCallback = null)
|
810 |
+
{
|
811 |
+
// build parameters
|
812 |
+
$parameters = array();
|
813 |
+
$parameters['oauth_token'] = (string) $oauthToken;
|
814 |
+
if($oauthCallback !== null) $parameters['oauth_callback'] = (string) $oauthCallback;
|
815 |
+
|
816 |
+
// build url
|
817 |
+
$url = self::API_AUTH_URL . '/1/oauth/authorize?' . http_build_query($parameters);
|
818 |
+
|
819 |
+
return $url;
|
820 |
+
}
|
821 |
+
|
822 |
+
/**
|
823 |
+
* This call returns a access token and the corresponding access token secret.
|
824 |
+
* Upon return, the authorization process is now complete and the access token and corresponding secret are used to sign requests for the metadata and file content API calls.
|
825 |
+
*
|
826 |
+
* @return array
|
827 |
+
* @param string $oauthToken The token returned after authorizing.
|
828 |
+
*/
|
829 |
+
public function oAuthAccessToken($oauthToken)
|
830 |
+
{
|
831 |
+
// build parameters
|
832 |
+
$parameters = array();
|
833 |
+
$parameters['oauth_token'] = (string) $oauthToken;
|
834 |
+
|
835 |
+
// make the call
|
836 |
+
$response = $this->doOAuthCall('1/oauth/access_token', $parameters, 'POST', false);
|
837 |
+
|
838 |
+
// process response
|
839 |
+
$response = (array) explode('&', $response);
|
840 |
+
$return = array();
|
841 |
+
|
842 |
+
// loop chunks
|
843 |
+
foreach($response as $chunk)
|
844 |
+
{
|
845 |
+
// split again
|
846 |
+
$chunks = explode('=', $chunk, 2);
|
847 |
+
|
848 |
+
// store return
|
849 |
+
if(count($chunks) == 2) $return[$chunks[0]] = $chunks[1];
|
850 |
+
}
|
851 |
+
|
852 |
+
// return
|
853 |
+
return $return;
|
854 |
+
}
|
855 |
+
|
856 |
+
|
857 |
+
// token resources
|
858 |
+
/**
|
859 |
+
* The token call provides a consumer/secret key pair you can use to consistently access the user's account.
|
860 |
+
* This is the preferred method of authentication over storing the username and password.
|
861 |
+
* Use the key pair as a signature with every subsequent call.
|
862 |
+
* The request must be signed using the application's developer and secret key token. Request or access tokens are necessary.
|
863 |
+
*
|
864 |
+
* Warning: DO NOT STORE THE USER'S PASSWORD! The way this call works is you call it once with the user's email and password and then
|
865 |
+
* keep the token around for later. You do NOT (I repeat NOT) call this before everything you do or on each program startup.
|
866 |
+
* We watch for this and will shut down your application with little notice if we catch you.
|
867 |
+
* In fact, the Objective-C code does this for you so you can't get it wrong.
|
868 |
+
*
|
869 |
+
* @return array Upon successful verification of the user's credentials, returns an array representation of the access token and secret.
|
870 |
+
* @param string $email The email account of the user.
|
871 |
+
* @param string $password The password of the user.
|
872 |
+
*/
|
873 |
+
public function token($email, $password)
|
874 |
+
{
|
875 |
+
// build parameters
|
876 |
+
$parameters = array();
|
877 |
+
$parameters['email'] = (string) $email;
|
878 |
+
$parameters['password'] = (string) $password;
|
879 |
+
|
880 |
+
// make the call
|
881 |
+
$response = (array) $this->doOAuthCall('1/token', $parameters);
|
882 |
+
|
883 |
+
// validate and set
|
884 |
+
if(isset($response['token'])) $this->setOAuthToken($response['token']);
|
885 |
+
if(isset($response['secret'])) $this->setOAuthTokenSecret($response['secret']);
|
886 |
+
|
887 |
+
// return
|
888 |
+
return $response;
|
889 |
+
}
|
890 |
+
|
891 |
+
|
892 |
+
// account resources
|
893 |
+
/**
|
894 |
+
* Given a set of account information, the account call allows an application to create a new Dropbox user account.
|
895 |
+
* This is useful for situations where the trusted third party application is possibly the user's first interaction with Dropbox.
|
896 |
+
*
|
897 |
+
* @return bool
|
898 |
+
* @param string $email The email account of the user.
|
899 |
+
* @param string $password The password for the user.
|
900 |
+
* @param string $firstName The user's first name.
|
901 |
+
* @param string $lastName The user's last name.
|
902 |
+
*/
|
903 |
+
public function account($email, $password, $firstName, $lastName)
|
904 |
+
{
|
905 |
+
// build parameters
|
906 |
+
$parameters['email'] = (string) $email;
|
907 |
+
$parameters['first_name'] = (string) $firstName;
|
908 |
+
$parameters['last_name'] = (string) $lastName;
|
909 |
+
$parameters['password'] = (string) $password;
|
910 |
+
|
911 |
+
return (bool) ($this->doCall('1/account', $parameters, 'POST', null, false) == 'OK');
|
912 |
+
}
|
913 |
+
|
914 |
+
|
915 |
+
/**
|
916 |
+
* Get the user account information.
|
917 |
+
*
|
918 |
+
* @return array
|
919 |
+
*/
|
920 |
+
public function accountInfo()
|
921 |
+
{
|
922 |
+
// make the call
|
923 |
+
return (array) $this->doCall('1/account/info');
|
924 |
+
}
|
925 |
+
|
926 |
+
|
927 |
+
// files & metadata
|
928 |
+
/**
|
929 |
+
* Retrieves file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
|
930 |
+
*
|
931 |
+
* @return string
|
932 |
+
* @param string $path Path of the directory wherin the file is located.
|
933 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
934 |
+
*/
|
935 |
+
public function filesGet($path, $sandbox = false)
|
936 |
+
{
|
937 |
+
// build url
|
938 |
+
$url = '1/files/';
|
939 |
+
$url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
|
940 |
+
$url .= trim((string) $path, '/');
|
941 |
+
|
942 |
+
// make the call
|
943 |
+
return $this->doCall($url, null, 'GET', null, false, true);
|
944 |
+
}
|
945 |
+
|
946 |
+
|
947 |
+
/**
|
948 |
+
* Uploads file contents relative to the user's Dropbox root or the application's directory within the user's Dropbox.
|
949 |
+
*
|
950 |
+
* @return bool
|
951 |
+
* @param string $path Path of the directory wherin the file should be uploaded.
|
952 |
+
* @param string $localFile Path to the local file.
|
953 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
954 |
+
*/
|
955 |
+
public function filesPost($path, $localFile, $sandbox = false)
|
956 |
+
{
|
957 |
+
// build url
|
958 |
+
$url = '1/files/';
|
959 |
+
$url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
|
960 |
+
$url .= trim((string) $path, '/');
|
961 |
+
|
962 |
+
// make the call
|
963 |
+
$return = $this->doCall($url, null, 'POST', $localFile, true, true);
|
964 |
+
// return the result
|
965 |
+
return (bool) (isset($return['size']) && $return['size'] == 'winner!');
|
966 |
+
}
|
967 |
+
|
968 |
+
|
969 |
+
/**
|
970 |
+
* Returns metadata for the file or directory at the given <path> location relative to the user's Dropbox or
|
971 |
+
* the user's application sandbox. If <path> represents a directory and the list parameter is true, the metadata will
|
972 |
+
* also include a listing of metadata for the directory's contents.
|
973 |
+
*
|
974 |
+
* @return array
|
975 |
+
* @param string[optional] $path The path to the file/director to get the metadata for.
|
976 |
+
* @param int[optional] $fileLimit When listing a directory, the service will not report listings containing more than $fileLimit files.
|
977 |
+
* @param bool[optional] $hash Listing return values include a hash representing the state of the directory's contents.
|
978 |
+
* @param bool[optional] $list If true, this call returns a list of metadata representations for the contents of the directory. If false, this call returns the metadata for the directory itself.
|
979 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
980 |
+
*/
|
981 |
+
public function metadata($path = '', $fileLimit = 10000, $hash = false, $list = true, $sandbox = false)
|
982 |
+
{
|
983 |
+
// build url
|
984 |
+
$url = '1/metadata/';
|
985 |
+
$url .= ($sandbox) ? 'sandbox/' : 'dropbox/';
|
986 |
+
$url .= trim((string) $path, '/');
|
987 |
+
|
988 |
+
// build parameters
|
989 |
+
$parameters = null;
|
990 |
+
$parameters['file_limit'] = (int) $fileLimit;
|
991 |
+
if((bool) $hash) $parameters['hash'] = '';
|
992 |
+
$parameters['list'] = ($list) ? 'true': 'false';
|
993 |
+
|
994 |
+
// make the call
|
995 |
+
return (array) $this->doCall($url, $parameters);
|
996 |
+
}
|
997 |
+
|
998 |
+
|
999 |
+
/**
|
1000 |
+
* Get a minimized thumbnail for a photo.
|
1001 |
+
*
|
1002 |
+
* @return string Will return a base64_encode string with the JPEG-data
|
1003 |
+
* @param string $path The path to the photo.
|
1004 |
+
* @param string[optional] $size The size, possible values are: 'small' (32x32), 'medium' (64x64), 'large' (128x128).
|
1005 |
+
*/
|
1006 |
+
public function thumbnails($path, $size = 'small')
|
1007 |
+
{
|
1008 |
+
// build url
|
1009 |
+
$url = '1/thumbnails/dropbox/';
|
1010 |
+
$url .= trim((string) $path, '/');
|
1011 |
+
|
1012 |
+
// build parameters
|
1013 |
+
$parameters['size'] = (string) $size;
|
1014 |
+
|
1015 |
+
// make the call
|
1016 |
+
return $this->doCall($url, $parameters, 'GET', null, false, true);
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
|
1020 |
+
// file operations
|
1021 |
+
/**
|
1022 |
+
* Copy a file or folder to a new location.
|
1023 |
+
*
|
1024 |
+
* @return array
|
1025 |
+
* @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
|
1026 |
+
* @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
|
1027 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
1028 |
+
*/
|
1029 |
+
public function fileopsCopy($fromPath, $toPath, $sandbox = false)
|
1030 |
+
{
|
1031 |
+
// build url
|
1032 |
+
$url = '1/fileops/copy';
|
1033 |
+
|
1034 |
+
// build parameters
|
1035 |
+
$parameters['from_path'] = (string) $fromPath;
|
1036 |
+
$parameters['to_path'] = (string) $toPath;
|
1037 |
+
$parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
|
1038 |
+
|
1039 |
+
// make the call
|
1040 |
+
return $this->doCall($url, $parameters, 'POST');
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
|
1044 |
+
/**
|
1045 |
+
* Create a folder relative to the user's Dropbox root or the user's application sandbox folder.
|
1046 |
+
*
|
1047 |
+
* @return array
|
1048 |
+
* @param string $path The path to the new folder to create, relative to root.
|
1049 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
1050 |
+
*/
|
1051 |
+
public function fileopsCreateFolder($path, $sandbox = false)
|
1052 |
+
{
|
1053 |
+
// build url
|
1054 |
+
$url = '1/fileops/create_folder';
|
1055 |
+
|
1056 |
+
// build parameters
|
1057 |
+
$parameters['path'] = trim((string) $path, '/');
|
1058 |
+
$parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
|
1059 |
+
|
1060 |
+
// make the call
|
1061 |
+
return $this->doCall($url, $parameters, 'POST');
|
1062 |
+
}
|
1063 |
+
|
1064 |
+
|
1065 |
+
/**
|
1066 |
+
* Deletes a file or folder.
|
1067 |
+
*
|
1068 |
+
* @return array
|
1069 |
+
* @param string $path path specifies either a file or folder to be deleted. This path is interpreted relative to the location specified by root.
|
1070 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
1071 |
+
*/
|
1072 |
+
public function fileopsDelete($path, $sandbox = false)
|
1073 |
+
{
|
1074 |
+
// build url
|
1075 |
+
$url = '1/fileops/delete';
|
1076 |
+
|
1077 |
+
// build parameters
|
1078 |
+
$parameters['path'] = trim((string) $path, '/');
|
1079 |
+
$parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
|
1080 |
+
// make the call
|
1081 |
+
return $this->doCall($url, $parameters, 'POST');
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
|
1085 |
+
/**
|
1086 |
+
* Move a file or folder to a new location.
|
1087 |
+
*
|
1088 |
+
* @return array
|
1089 |
+
* @param string $fromPath fromPath specifies either a file or folder to be copied to the location specified by toPath. This path is interpreted relative to the location specified by root.
|
1090 |
+
* @param string $toPath toPath specifies the destination path including the new name for file or folder. This path is interpreted relative to the location specified by root.
|
1091 |
+
* @param bool[optional] $sandbox Sandbox mode?
|
1092 |
+
*/
|
1093 |
+
public function fileopsMove($fromPath, $toPath, $sandbox = false)
|
1094 |
+
{
|
1095 |
+
// build url
|
1096 |
+
$url = '1/fileops/move';
|
1097 |
+
|
1098 |
+
// build parameters
|
1099 |
+
$parameters['from_path'] = (string) $fromPath;
|
1100 |
+
$parameters['to_path'] = (string) $toPath;
|
1101 |
+
$parameters['root'] = ($sandbox) ? 'sandbox' : 'dropbox';
|
1102 |
+
|
1103 |
+
// make the call
|
1104 |
+
return $this->doCall($url, $parameters, 'POST');
|
1105 |
+
}
|
1106 |
+
|
1107 |
+
function _log($mixed)
|
1108 |
+
{
|
1109 |
+
if (is_array($mixed)) {
|
1110 |
+
$mixed = print_r($mixed, 1);
|
1111 |
+
} else if (is_object($mixed)) {
|
1112 |
+
ob_start();
|
1113 |
+
var_dump($mixed);
|
1114 |
+
$mixed = ob_get_clean();
|
1115 |
+
}
|
1116 |
+
|
1117 |
+
$handle = fopen(dirname(__FILE__) . '/log', 'a');
|
1118 |
+
fwrite($handle, $mixed . PHP_EOL);
|
1119 |
+
fclose($handle);
|
1120 |
+
}
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
|
1124 |
+
/**
|
1125 |
+
* Dropbox Exception class
|
1126 |
+
*
|
1127 |
+
* @author Tijs Verkoyen <php-dropbox@verkoyen.eu>
|
1128 |
+
*/
|
1129 |
+
class DropboxException extends Exception
|
1130 |
+
{
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
?>
|
lib/dropbox.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Dropbox Uploader
|
4 |
+
*
|
5 |
+
* Copyright (c) 2009 Jaka Jancar
|
6 |
+
*
|
7 |
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
* of this software and associated documentation files (the "Software"), to deal
|
9 |
+
* in the Software without restriction, including without limitation the rights
|
10 |
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
* copies of the Software, and to permit persons to whom the Software is
|
12 |
+
* furnished to do so, subject to the following conditions:
|
13 |
+
*
|
14 |
+
* The above copyright notice and this permission notice shall be included in
|
15 |
+
* all copies or substantial portions of the Software.
|
16 |
+
*
|
17 |
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
* THE SOFTWARE.
|
24 |
+
*
|
25 |
+
* @author Jaka Jancar [jaka@kubje.org] [http://jaka.kubje.org/]
|
26 |
+
* @version 1.1.5
|
27 |
+
*/
|
28 |
+
class DropboxUploader {
|
29 |
+
protected $email;
|
30 |
+
protected $password;
|
31 |
+
protected $caCertSourceType = self::CACERT_SOURCE_SYSTEM;
|
32 |
+
const CACERT_SOURCE_SYSTEM = 0;
|
33 |
+
const CACERT_SOURCE_FILE = 1;
|
34 |
+
const CACERT_SOURCE_DIR = 2;
|
35 |
+
protected $caCertSource;
|
36 |
+
protected $loggedIn = false;
|
37 |
+
protected $cookies = array();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor
|
41 |
+
*
|
42 |
+
* @param string $email
|
43 |
+
* @param string|null $password
|
44 |
+
*/
|
45 |
+
public function __construct($email, $password) {
|
46 |
+
// Check requirements
|
47 |
+
if (!extension_loaded('curl'))
|
48 |
+
throw new Exception('DropboxUploader requires the cURL extension.');
|
49 |
+
|
50 |
+
$this->email = $email;
|
51 |
+
$this->password = $password;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function setCaCertificateFile($file)
|
55 |
+
{
|
56 |
+
$this->caCertSourceType = self::CACERT_SOURCE_FILE;
|
57 |
+
$this->caCertSource = $file;
|
58 |
+
}
|
59 |
+
|
60 |
+
public function setCaCertificateDir($dir)
|
61 |
+
{
|
62 |
+
$this->caCertSourceType = self::CACERT_SOURCE_DIR;
|
63 |
+
$this->caCertSource = $dir;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function upload($filename, $remoteDir='/') {
|
67 |
+
if (!file_exists($filename) or !is_file($filename) or !is_readable($filename))
|
68 |
+
throw new Exception("File '$filename' does not exist or is not readable.");
|
69 |
+
|
70 |
+
if (!is_string($remoteDir))
|
71 |
+
throw new Exception("Remote directory must be a string, is ".gettype($remoteDir)." instead.");
|
72 |
+
|
73 |
+
if (!$this->loggedIn)
|
74 |
+
$this->login();
|
75 |
+
|
76 |
+
$data = $this->request('https://www.dropbox.com/home');
|
77 |
+
$token = $this->extractToken($data, 'https://dl-web.dropbox.com/upload');
|
78 |
+
|
79 |
+
$data = $this->request('https://dl-web.dropbox.com/upload', true, array('plain'=>'yes', 'file'=>'@'.$filename, 'dest'=>$remoteDir, 't'=>$token));
|
80 |
+
if (strpos($data, 'HTTP/1.1 302 FOUND') === false)
|
81 |
+
throw new Exception('Upload failed!');
|
82 |
+
}
|
83 |
+
|
84 |
+
protected function login() {
|
85 |
+
$data = $this->request('https://www.dropbox.com/login');
|
86 |
+
$token = $this->extractToken($data, '/login');
|
87 |
+
|
88 |
+
$data = $this->request('https://www.dropbox.com/login', true, array('login_email'=>$this->email, 'login_password'=>$this->password, 't'=>$token));
|
89 |
+
|
90 |
+
if (stripos($data, 'location: /home') === false)
|
91 |
+
throw new Exception('Login unsuccessful.');
|
92 |
+
|
93 |
+
$this->loggedIn = true;
|
94 |
+
}
|
95 |
+
|
96 |
+
protected function request($url, $post=false, $postData=array()) {
|
97 |
+
$ch = curl_init();
|
98 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
99 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
100 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
101 |
+
switch ($this->caCertSourceType) {
|
102 |
+
case self::CACERT_SOURCE_FILE:
|
103 |
+
curl_setopt($ch, CURLOPT_CAINFO, $this->caCertSource);
|
104 |
+
break;
|
105 |
+
case self::CACERT_SOURCE_DIR:
|
106 |
+
curl_setopt($ch, CURLOPT_CAPATH, $this->caCertSource);
|
107 |
+
break;
|
108 |
+
}
|
109 |
+
curl_setopt($ch, CURLOPT_HEADER, 1);
|
110 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
111 |
+
if ($post) {
|
112 |
+
curl_setopt($ch, CURLOPT_POST, $post);
|
113 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, array_map('stripcslashes', $postData));
|
114 |
+
}
|
115 |
+
|
116 |
+
// Send cookies
|
117 |
+
$rawCookies = array();
|
118 |
+
foreach ($this->cookies as $k=>$v)
|
119 |
+
$rawCookies[] = "$k=$v";
|
120 |
+
$rawCookies = implode(';', $rawCookies);
|
121 |
+
curl_setopt($ch, CURLOPT_COOKIE, $rawCookies);
|
122 |
+
|
123 |
+
$data = curl_exec($ch);
|
124 |
+
|
125 |
+
if ($data === false)
|
126 |
+
throw new Exception('Cannot execute request: '.curl_error($ch));
|
127 |
+
|
128 |
+
// Store received cookies
|
129 |
+
preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER);
|
130 |
+
foreach ($matches as $match)
|
131 |
+
$this->cookies[$match[1]] = $match[2];
|
132 |
+
|
133 |
+
curl_close($ch);
|
134 |
+
|
135 |
+
return $data;
|
136 |
+
}
|
137 |
+
|
138 |
+
protected function extractToken($html, $formAction) {
|
139 |
+
if (!preg_match('/<form [^>]*'.preg_quote($formAction, '/').'[^>]*>.*?(<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is', $html, $matches) || !isset($matches[2]))
|
140 |
+
throw new Exception("Cannot extract token! (form action=$formAction)");
|
141 |
+
return $matches[2];
|
142 |
+
}
|
143 |
+
|
144 |
+
}
|
lib/s3.php
ADDED
@@ -0,0 +1,1966 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* $Id$
|
4 |
+
*
|
5 |
+
* Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
|
6 |
+
*
|
7 |
+
* Redistribution and use in source and binary forms, with or without
|
8 |
+
* modification, are permitted provided that the following conditions are met:
|
9 |
+
*
|
10 |
+
* - Redistributions of source code must retain the above copyright notice,
|
11 |
+
* this list of conditions and the following disclaimer.
|
12 |
+
* - Redistributions in binary form must reproduce the above copyright
|
13 |
+
* notice, this list of conditions and the following disclaimer in the
|
14 |
+
* documentation and/or other materials provided with the distribution.
|
15 |
+
*
|
16 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17 |
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19 |
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
20 |
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
21 |
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
22 |
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
23 |
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
24 |
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
25 |
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
26 |
+
* POSSIBILITY OF SUCH DAMAGE.
|
27 |
+
*
|
28 |
+
* Amazon S3 is a trademark of Amazon.com, Inc. or its affiliates.
|
29 |
+
*/
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Amazon S3 PHP class
|
33 |
+
*
|
34 |
+
* @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
|
35 |
+
* @version 0.5.0-dev
|
36 |
+
*/
|
37 |
+
class S3
|
38 |
+
{
|
39 |
+
// ACL flags
|
40 |
+
const ACL_PRIVATE = 'private';
|
41 |
+
const ACL_PUBLIC_READ = 'public-read';
|
42 |
+
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
|
43 |
+
const ACL_AUTHENTICATED_READ = 'authenticated-read';
|
44 |
+
|
45 |
+
const STORAGE_CLASS_STANDARD = 'STANDARD';
|
46 |
+
const STORAGE_CLASS_RRS = 'REDUCED_REDUNDANCY';
|
47 |
+
|
48 |
+
private static $__accessKey = null; // AWS Access key
|
49 |
+
private static $__secretKey = null; // AWS Secret key
|
50 |
+
private static $__sslKey = null;
|
51 |
+
|
52 |
+
public static $endpoint = 's3.amazonaws.com';
|
53 |
+
public static $proxy = null;
|
54 |
+
|
55 |
+
public static $useSSL = false;
|
56 |
+
public static $useSSLValidation = true;
|
57 |
+
public static $useExceptions = false;
|
58 |
+
|
59 |
+
// SSL CURL SSL options - only needed if you are experiencing problems with your OpenSSL configuration
|
60 |
+
public static $sslKey = null;
|
61 |
+
public static $sslCert = null;
|
62 |
+
public static $sslCACert = null;
|
63 |
+
|
64 |
+
private static $__signingKeyPairId = null; // AWS Key Pair ID
|
65 |
+
private static $__signingKeyResource = false; // Key resource, freeSigningKey() must be called to clear it from memory
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Constructor - if you're not using the class statically
|
70 |
+
*
|
71 |
+
* @param string $accessKey Access key
|
72 |
+
* @param string $secretKey Secret key
|
73 |
+
* @param boolean $useSSL Enable SSL
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com')
|
77 |
+
{
|
78 |
+
if ($accessKey !== null && $secretKey !== null)
|
79 |
+
self::setAuth($accessKey, $secretKey);
|
80 |
+
self::$useSSL = $useSSL;
|
81 |
+
self::$endpoint = $endpoint;
|
82 |
+
}
|
83 |
+
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set the sertvice endpoint
|
87 |
+
*
|
88 |
+
* @param string $host Hostname
|
89 |
+
* @return void
|
90 |
+
*/
|
91 |
+
public function setEndpoint($host)
|
92 |
+
{
|
93 |
+
self::$endpoint = $host;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Set AWS access key and secret key
|
98 |
+
*
|
99 |
+
* @param string $accessKey Access key
|
100 |
+
* @param string $secretKey Secret key
|
101 |
+
* @return void
|
102 |
+
*/
|
103 |
+
public static function setAuth($accessKey, $secretKey)
|
104 |
+
{
|
105 |
+
self::$__accessKey = $accessKey;
|
106 |
+
self::$__secretKey = $secretKey;
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Check if AWS keys have been set
|
112 |
+
*
|
113 |
+
* @return boolean
|
114 |
+
*/
|
115 |
+
public static function hasAuth() {
|
116 |
+
return (self::$__accessKey !== null && self::$__secretKey !== null);
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Set SSL on or off
|
122 |
+
*
|
123 |
+
* @param boolean $enabled SSL enabled
|
124 |
+
* @param boolean $validate SSL certificate validation
|
125 |
+
* @return void
|
126 |
+
*/
|
127 |
+
public static function setSSL($enabled, $validate = true)
|
128 |
+
{
|
129 |
+
self::$useSSL = $enabled;
|
130 |
+
self::$useSSLValidation = $validate;
|
131 |
+
}
|
132 |
+
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Set SSL client certificates (experimental)
|
136 |
+
*
|
137 |
+
* @param string $sslCert SSL client certificate
|
138 |
+
* @param string $sslKey SSL client key
|
139 |
+
* @param string $sslCACert SSL CA cert (only required if you are having problems with your system CA cert)
|
140 |
+
* @return void
|
141 |
+
*/
|
142 |
+
public static function setSSLAuth($sslCert = null, $sslKey = null, $sslCACert = null)
|
143 |
+
{
|
144 |
+
self::$sslCert = $sslCert;
|
145 |
+
self::$sslKey = $sslKey;
|
146 |
+
self::$sslCACert = $sslCACert;
|
147 |
+
}
|
148 |
+
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Set proxy information
|
152 |
+
*
|
153 |
+
* @param string $host Proxy hostname and port (localhost:1234)
|
154 |
+
* @param string $user Proxy username
|
155 |
+
* @param string $pass Proxy password
|
156 |
+
* @param constant $type CURL proxy type
|
157 |
+
* @return void
|
158 |
+
*/
|
159 |
+
public static function setProxy($host, $user = null, $pass = null, $type = CURLPROXY_SOCKS5)
|
160 |
+
{
|
161 |
+
self::$proxy = array('host' => $host, 'type' => $type, 'user' => null, 'pass' => 'null');
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Set the error mode to exceptions
|
167 |
+
*
|
168 |
+
* @param boolean $enabled Enable exceptions
|
169 |
+
* @return void
|
170 |
+
*/
|
171 |
+
public static function setExceptions($enabled = true)
|
172 |
+
{
|
173 |
+
self::$useExceptions = $enabled;
|
174 |
+
}
|
175 |
+
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Set signing key
|
179 |
+
*
|
180 |
+
* @param string $keyPairId AWS Key Pair ID
|
181 |
+
* @param string $signingKey Private Key
|
182 |
+
* @param boolean $isFile Load private key from file, set to false to load string
|
183 |
+
* @return boolean
|
184 |
+
*/
|
185 |
+
public static function setSigningKey($keyPairId, $signingKey, $isFile = true)
|
186 |
+
{
|
187 |
+
self::$__signingKeyPairId = $keyPairId;
|
188 |
+
if ((self::$__signingKeyResource = openssl_pkey_get_private($isFile ?
|
189 |
+
file_get_contents($signingKey) : $signingKey)) !== false) return true;
|
190 |
+
self::__triggerError('S3::setSigningKey(): Unable to open load private key: '.$signingKey, __FILE__, __LINE__);
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Free signing key from memory, MUST be called if you are using setSigningKey()
|
197 |
+
*
|
198 |
+
* @return void
|
199 |
+
*/
|
200 |
+
public static function freeSigningKey()
|
201 |
+
{
|
202 |
+
if (self::$__signingKeyResource !== false)
|
203 |
+
openssl_free_key(self::$__signingKeyResource);
|
204 |
+
}
|
205 |
+
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Internal error handler
|
209 |
+
*
|
210 |
+
* @internal Internal error handler
|
211 |
+
* @param string $message Error message
|
212 |
+
* @param string $file Filename
|
213 |
+
* @param integer $line Line number
|
214 |
+
* @param integer $code Error code
|
215 |
+
* @return void
|
216 |
+
*/
|
217 |
+
private static function __triggerError($message, $file, $line, $code = 0)
|
218 |
+
{
|
219 |
+
|
220 |
+
//if (self::$useExceptions)
|
221 |
+
throw new mwpS3Exception($message, $file, $line, $code);
|
222 |
+
//else
|
223 |
+
//trigger_error($message, E_USER_WARNING);
|
224 |
+
}
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Get a list of buckets
|
229 |
+
*
|
230 |
+
* @param boolean $detailed Returns detailed bucket list when true
|
231 |
+
* @return array | false
|
232 |
+
*/
|
233 |
+
public static function listBuckets($detailed = false)
|
234 |
+
{
|
235 |
+
$rest = new iwpS3Request('GET', '', '', self::$endpoint);
|
236 |
+
$rest = $rest->getResponse();
|
237 |
+
if ($rest->error === false && $rest->code !== 200)
|
238 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
239 |
+
if ($rest->error !== false)
|
240 |
+
{
|
241 |
+
self::__triggerError(sprintf("S3::listBuckets(): [%s] %s", $rest->error['code'],
|
242 |
+
$rest->error['message']), __FILE__, __LINE__);
|
243 |
+
return false;
|
244 |
+
}
|
245 |
+
$results = array();
|
246 |
+
if (!isset($rest->body->Buckets)) return $results;
|
247 |
+
|
248 |
+
if ($detailed)
|
249 |
+
{
|
250 |
+
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
|
251 |
+
$results['owner'] = array(
|
252 |
+
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
|
253 |
+
);
|
254 |
+
$results['buckets'] = array();
|
255 |
+
foreach ($rest->body->Buckets->Bucket as $b)
|
256 |
+
$results['buckets'][] = array(
|
257 |
+
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
|
258 |
+
);
|
259 |
+
} else
|
260 |
+
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
|
261 |
+
|
262 |
+
return $results;
|
263 |
+
}
|
264 |
+
|
265 |
+
|
266 |
+
/*
|
267 |
+
* Get contents for a bucket
|
268 |
+
*
|
269 |
+
* If maxKeys is null this method will loop through truncated result sets
|
270 |
+
*
|
271 |
+
* @param string $bucket Bucket name
|
272 |
+
* @param string $prefix Prefix
|
273 |
+
* @param string $marker Marker (last file listed)
|
274 |
+
* @param string $maxKeys Max keys (maximum number of keys to return)
|
275 |
+
* @param string $delimiter Delimiter
|
276 |
+
* @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
|
277 |
+
* @return array | false
|
278 |
+
*/
|
279 |
+
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false)
|
280 |
+
{
|
281 |
+
$rest = new iwpS3Request('GET', $bucket, '', self::$endpoint);
|
282 |
+
if ($maxKeys == 0) $maxKeys = null;
|
283 |
+
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
284 |
+
if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
|
285 |
+
if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
|
286 |
+
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
287 |
+
$response = $rest->getResponse();
|
288 |
+
if ($response->error === false && $response->code !== 200)
|
289 |
+
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
|
290 |
+
if ($response->error !== false)
|
291 |
+
{
|
292 |
+
self::__triggerError(sprintf("S3::getBucket(): [%s] %s",
|
293 |
+
$response->error['code'], $response->error['message']), __FILE__, __LINE__);
|
294 |
+
return false;
|
295 |
+
}
|
296 |
+
|
297 |
+
$results = array();
|
298 |
+
|
299 |
+
$nextMarker = null;
|
300 |
+
if (isset($response->body, $response->body->Contents))
|
301 |
+
foreach ($response->body->Contents as $c)
|
302 |
+
{
|
303 |
+
$results[(string)$c->Key] = array(
|
304 |
+
'name' => (string)$c->Key,
|
305 |
+
'time' => strtotime((string)$c->LastModified),
|
306 |
+
'size' => (int)$c->Size,
|
307 |
+
'hash' => substr((string)$c->ETag, 1, -1)
|
308 |
+
);
|
309 |
+
$nextMarker = (string)$c->Key;
|
310 |
+
}
|
311 |
+
|
312 |
+
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
313 |
+
foreach ($response->body->CommonPrefixes as $c)
|
314 |
+
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
315 |
+
|
316 |
+
if (isset($response->body, $response->body->IsTruncated) &&
|
317 |
+
(string)$response->body->IsTruncated == 'false') return $results;
|
318 |
+
|
319 |
+
if (isset($response->body, $response->body->NextMarker))
|
320 |
+
$nextMarker = (string)$response->body->NextMarker;
|
321 |
+
|
322 |
+
// Loop through truncated results if maxKeys isn't specified
|
323 |
+
if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
|
324 |
+
do
|
325 |
+
{
|
326 |
+
$rest = new iwpS3Request('GET', $bucket, '', self::$endpoint);
|
327 |
+
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
328 |
+
$rest->setParameter('marker', $nextMarker);
|
329 |
+
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
330 |
+
|
331 |
+
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
|
332 |
+
|
333 |
+
if (isset($response->body, $response->body->Contents))
|
334 |
+
foreach ($response->body->Contents as $c)
|
335 |
+
{
|
336 |
+
$results[(string)$c->Key] = array(
|
337 |
+
'name' => (string)$c->Key,
|
338 |
+
'time' => strtotime((string)$c->LastModified),
|
339 |
+
'size' => (int)$c->Size,
|
340 |
+
'hash' => substr((string)$c->ETag, 1, -1)
|
341 |
+
);
|
342 |
+
$nextMarker = (string)$c->Key;
|
343 |
+
}
|
344 |
+
|
345 |
+
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
346 |
+
foreach ($response->body->CommonPrefixes as $c)
|
347 |
+
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
348 |
+
|
349 |
+
if (isset($response->body, $response->body->NextMarker))
|
350 |
+
$nextMarker = (string)$response->body->NextMarker;
|
351 |
+
|
352 |
+
} while ($response !== false && (string)$response->body->IsTruncated == 'true');
|
353 |
+
|
354 |
+
return $results;
|
355 |
+
}
|
356 |
+
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Put a bucket
|
360 |
+
*
|
361 |
+
* @param string $bucket Bucket name
|
362 |
+
* @param constant $acl ACL flag
|
363 |
+
* @param string $location Set as "EU" to create buckets hosted in Europe
|
364 |
+
* @return boolean
|
365 |
+
*/
|
366 |
+
public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false)
|
367 |
+
{
|
368 |
+
$rest = new iwpS3Request('PUT', $bucket, '', self::$endpoint);
|
369 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
370 |
+
|
371 |
+
if ($location !== false)
|
372 |
+
{
|
373 |
+
$dom = new DOMDocument;
|
374 |
+
$createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
|
375 |
+
$locationConstraint = $dom->createElement('LocationConstraint', $location);
|
376 |
+
$createBucketConfiguration->appendChild($locationConstraint);
|
377 |
+
$dom->appendChild($createBucketConfiguration);
|
378 |
+
$rest->data = $dom->saveXML();
|
379 |
+
$rest->size = strlen($rest->data);
|
380 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
381 |
+
}
|
382 |
+
$rest = $rest->getResponse();
|
383 |
+
|
384 |
+
if ($rest->error === false && $rest->code !== 200)
|
385 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
386 |
+
if ($rest->error !== false)
|
387 |
+
{
|
388 |
+
self::__triggerError(sprintf("S3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
|
389 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
390 |
+
return false;
|
391 |
+
}
|
392 |
+
return true;
|
393 |
+
}
|
394 |
+
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Delete an empty bucket
|
398 |
+
*
|
399 |
+
* @param string $bucket Bucket name
|
400 |
+
* @return boolean
|
401 |
+
*/
|
402 |
+
public static function deleteBucket($bucket)
|
403 |
+
{
|
404 |
+
$rest = new iwpS3Request('DELETE', $bucket, '', self::$endpoint);
|
405 |
+
$rest = $rest->getResponse();
|
406 |
+
if ($rest->error === false && $rest->code !== 204)
|
407 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
408 |
+
if ($rest->error !== false)
|
409 |
+
{
|
410 |
+
self::__triggerError(sprintf("S3::deleteBucket({$bucket}): [%s] %s",
|
411 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
412 |
+
return false;
|
413 |
+
}
|
414 |
+
return true;
|
415 |
+
}
|
416 |
+
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Create input info array for putObject()
|
420 |
+
*
|
421 |
+
* @param string $file Input file
|
422 |
+
* @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
|
423 |
+
* @return array | false
|
424 |
+
*/
|
425 |
+
public static function inputFile($file, $md5sum = true)
|
426 |
+
{
|
427 |
+
if (!file_exists($file) || !is_file($file) || !is_readable($file))
|
428 |
+
{
|
429 |
+
self::__triggerError('S3::inputFile(): Unable to open input file: '.$file, __FILE__, __LINE__);
|
430 |
+
return false;
|
431 |
+
}
|
432 |
+
return array('file' => $file, 'size' => filesize($file), 'md5sum' => $md5sum !== false ?
|
433 |
+
(is_string($md5sum) ? $md5sum : base64_encode(md5_file($file, true))) : '');
|
434 |
+
}
|
435 |
+
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Create input array info for putObject() with a resource
|
439 |
+
*
|
440 |
+
* @param string $resource Input resource to read from
|
441 |
+
* @param integer $bufferSize Input byte size
|
442 |
+
* @param string $md5sum MD5 hash to send (optional)
|
443 |
+
* @return array | false
|
444 |
+
*/
|
445 |
+
public static function inputResource(&$resource, $bufferSize, $md5sum = '')
|
446 |
+
{
|
447 |
+
if (!is_resource($resource) || $bufferSize < 0)
|
448 |
+
{
|
449 |
+
self::__triggerError('S3::inputResource(): Invalid resource or buffer size', __FILE__, __LINE__);
|
450 |
+
return false;
|
451 |
+
}
|
452 |
+
$input = array('size' => $bufferSize, 'md5sum' => $md5sum);
|
453 |
+
$input['fp'] =& $resource;
|
454 |
+
return $input;
|
455 |
+
}
|
456 |
+
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Put an object
|
460 |
+
*
|
461 |
+
* @param mixed $input Input data
|
462 |
+
* @param string $bucket Bucket name
|
463 |
+
* @param string $uri Object URI
|
464 |
+
* @param constant $acl ACL constant
|
465 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
466 |
+
* @param array $requestHeaders Array of request headers or content type as a string
|
467 |
+
* @param constant $storageClass Storage class constant
|
468 |
+
* @return boolean
|
469 |
+
*/
|
470 |
+
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
|
471 |
+
{
|
472 |
+
if ($input === false) return false;
|
473 |
+
$rest = new iwpS3Request('PUT', $bucket, $uri, self::$endpoint);
|
474 |
+
|
475 |
+
if (is_string($input)) $input = array(
|
476 |
+
'data' => $input, 'size' => strlen($input),
|
477 |
+
'md5sum' => base64_encode(md5($input, true))
|
478 |
+
);
|
479 |
+
|
480 |
+
// Data
|
481 |
+
if (isset($input['fp']))
|
482 |
+
$rest->fp =& $input['fp'];
|
483 |
+
elseif (isset($input['file']))
|
484 |
+
$rest->fp = @fopen($input['file'], 'rb');
|
485 |
+
elseif (isset($input['data']))
|
486 |
+
$rest->data = $input['data'];
|
487 |
+
|
488 |
+
// Content-Length (required)
|
489 |
+
if (isset($input['size']) && $input['size'] >= 0)
|
490 |
+
$rest->size = $input['size'];
|
491 |
+
else {
|
492 |
+
if (isset($input['file']))
|
493 |
+
$rest->size = filesize($input['file']);
|
494 |
+
elseif (isset($input['data']))
|
495 |
+
$rest->size = strlen($input['data']);
|
496 |
+
}
|
497 |
+
|
498 |
+
// Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
|
499 |
+
if (is_array($requestHeaders))
|
500 |
+
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
501 |
+
elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
|
502 |
+
$input['type'] = $requestHeaders;
|
503 |
+
|
504 |
+
// Content-Type
|
505 |
+
if (!isset($input['type']))
|
506 |
+
{
|
507 |
+
if (isset($requestHeaders['Content-Type']))
|
508 |
+
$input['type'] =& $requestHeaders['Content-Type'];
|
509 |
+
elseif (isset($input['file']))
|
510 |
+
$input['type'] = self::__getMimeType($input['file']);
|
511 |
+
else
|
512 |
+
$input['type'] = 'application/octet-stream';
|
513 |
+
}
|
514 |
+
|
515 |
+
if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
|
516 |
+
$rest->setAmzHeader('x-amz-storage-class', $storageClass);
|
517 |
+
|
518 |
+
// We need to post with Content-Length and Content-Type, MD5 is optional
|
519 |
+
if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false))
|
520 |
+
{
|
521 |
+
$rest->setHeader('Content-Type', $input['type']);
|
522 |
+
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
|
523 |
+
|
524 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
525 |
+
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
526 |
+
$rest->getResponse();
|
527 |
+
} else
|
528 |
+
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
|
529 |
+
|
530 |
+
if ($rest->response->error === false && $rest->response->code !== 200)
|
531 |
+
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
532 |
+
if ($rest->response->error !== false)
|
533 |
+
{
|
534 |
+
self::__triggerError(sprintf("S3::putObject(): [%s] %s",
|
535 |
+
$rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
|
536 |
+
return false;
|
537 |
+
}
|
538 |
+
return true;
|
539 |
+
}
|
540 |
+
|
541 |
+
|
542 |
+
/**
|
543 |
+
* Put an object from a file (legacy function)
|
544 |
+
*
|
545 |
+
* @param string $file Input file path
|
546 |
+
* @param string $bucket Bucket name
|
547 |
+
* @param string $uri Object URI
|
548 |
+
* @param constant $acl ACL constant
|
549 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
550 |
+
* @param string $contentType Content type
|
551 |
+
* @return boolean
|
552 |
+
*/
|
553 |
+
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null)
|
554 |
+
{
|
555 |
+
return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
|
556 |
+
}
|
557 |
+
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Put an object from a string (legacy function)
|
561 |
+
*
|
562 |
+
* @param string $string Input data
|
563 |
+
* @param string $bucket Bucket name
|
564 |
+
* @param string $uri Object URI
|
565 |
+
* @param constant $acl ACL constant
|
566 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
567 |
+
* @param string $contentType Content type
|
568 |
+
* @return boolean
|
569 |
+
*/
|
570 |
+
public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain')
|
571 |
+
{
|
572 |
+
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
|
573 |
+
}
|
574 |
+
|
575 |
+
|
576 |
+
/**
|
577 |
+
* Get an object
|
578 |
+
*
|
579 |
+
* @param string $bucket Bucket name
|
580 |
+
* @param string $uri Object URI
|
581 |
+
* @param mixed $saveTo Filename or resource to write to
|
582 |
+
* @return mixed
|
583 |
+
*/
|
584 |
+
public static function getObject($bucket, $uri, $saveTo = false)
|
585 |
+
{
|
586 |
+
$rest = new iwpS3Request('GET', $bucket, $uri, self::$endpoint);
|
587 |
+
if ($saveTo !== false)
|
588 |
+
{
|
589 |
+
if (is_resource($saveTo))
|
590 |
+
$rest->fp =& $saveTo;
|
591 |
+
else
|
592 |
+
if (($rest->fp = @fopen($saveTo, 'wb')) !== false)
|
593 |
+
$rest->file = realpath($saveTo);
|
594 |
+
else
|
595 |
+
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
|
596 |
+
}
|
597 |
+
if ($rest->response->error === false) $rest->getResponse();
|
598 |
+
|
599 |
+
if ($rest->response->error === false && $rest->response->code !== 200)
|
600 |
+
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
601 |
+
if ($rest->response->error !== false)
|
602 |
+
{
|
603 |
+
self::__triggerError(sprintf("S3::getObject({$bucket}, {$uri}): [%s] %s",
|
604 |
+
$rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
|
605 |
+
return false;
|
606 |
+
}
|
607 |
+
return $rest->response;
|
608 |
+
}
|
609 |
+
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Get object information
|
613 |
+
*
|
614 |
+
* @param string $bucket Bucket name
|
615 |
+
* @param string $uri Object URI
|
616 |
+
* @param boolean $returnInfo Return response information
|
617 |
+
* @return mixed | false
|
618 |
+
*/
|
619 |
+
public static function getObjectInfo($bucket, $uri, $returnInfo = true)
|
620 |
+
{
|
621 |
+
$rest = new iwpS3Request('HEAD', $bucket, $uri, self::$endpoint);
|
622 |
+
$rest = $rest->getResponse();
|
623 |
+
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
|
624 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
625 |
+
if ($rest->error !== false)
|
626 |
+
{
|
627 |
+
self::__triggerError(sprintf("S3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
|
628 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
629 |
+
return false;
|
630 |
+
}
|
631 |
+
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
|
632 |
+
}
|
633 |
+
|
634 |
+
|
635 |
+
/**
|
636 |
+
* Copy an object
|
637 |
+
*
|
638 |
+
* @param string $bucket Source bucket name
|
639 |
+
* @param string $uri Source object URI
|
640 |
+
* @param string $bucket Destination bucket name
|
641 |
+
* @param string $uri Destination object URI
|
642 |
+
* @param constant $acl ACL constant
|
643 |
+
* @param array $metaHeaders Optional array of x-amz-meta-* headers
|
644 |
+
* @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
|
645 |
+
* @param constant $storageClass Storage class constant
|
646 |
+
* @return mixed | false
|
647 |
+
*/
|
648 |
+
public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
|
649 |
+
{
|
650 |
+
$rest = new iwpS3Request('PUT', $bucket, $uri, self::$endpoint);
|
651 |
+
$rest->setHeader('Content-Length', 0);
|
652 |
+
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
653 |
+
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
654 |
+
if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
|
655 |
+
$rest->setAmzHeader('x-amz-storage-class', $storageClass);
|
656 |
+
$rest->setAmzHeader('x-amz-acl', $acl); // Added rawurlencode() for $srcUri (thanks a.yamanoi)
|
657 |
+
$rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, rawurlencode($srcUri)));
|
658 |
+
if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
|
659 |
+
$rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
|
660 |
+
|
661 |
+
$rest = $rest->getResponse();
|
662 |
+
if ($rest->error === false && $rest->code !== 200)
|
663 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
664 |
+
if ($rest->error !== false)
|
665 |
+
{
|
666 |
+
self::__triggerError(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
|
667 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
668 |
+
return false;
|
669 |
+
}
|
670 |
+
return isset($rest->body->LastModified, $rest->body->ETag) ? array(
|
671 |
+
'time' => strtotime((string)$rest->body->LastModified),
|
672 |
+
'hash' => substr((string)$rest->body->ETag, 1, -1)
|
673 |
+
) : false;
|
674 |
+
}
|
675 |
+
|
676 |
+
|
677 |
+
/**
|
678 |
+
* Set logging for a bucket
|
679 |
+
*
|
680 |
+
* @param string $bucket Bucket name
|
681 |
+
* @param string $targetBucket Target bucket (where logs are stored)
|
682 |
+
* @param string $targetPrefix Log prefix (e,g; domain.com-)
|
683 |
+
* @return boolean
|
684 |
+
*/
|
685 |
+
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null)
|
686 |
+
{
|
687 |
+
// The S3 log delivery group has to be added to the target bucket's ACP
|
688 |
+
if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false)
|
689 |
+
{
|
690 |
+
// Only add permissions to the target bucket when they do not exist
|
691 |
+
$aclWriteSet = false;
|
692 |
+
$aclReadSet = false;
|
693 |
+
foreach ($acp['acl'] as $acl)
|
694 |
+
if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery')
|
695 |
+
{
|
696 |
+
if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
|
697 |
+
elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
|
698 |
+
}
|
699 |
+
if (!$aclWriteSet) $acp['acl'][] = array(
|
700 |
+
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
|
701 |
+
);
|
702 |
+
if (!$aclReadSet) $acp['acl'][] = array(
|
703 |
+
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
|
704 |
+
);
|
705 |
+
if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
|
706 |
+
}
|
707 |
+
|
708 |
+
$dom = new DOMDocument;
|
709 |
+
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
|
710 |
+
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
|
711 |
+
if ($targetBucket !== null)
|
712 |
+
{
|
713 |
+
if ($targetPrefix == null) $targetPrefix = $bucket . '-';
|
714 |
+
$loggingEnabled = $dom->createElement('LoggingEnabled');
|
715 |
+
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
|
716 |
+
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
|
717 |
+
// TODO: Add TargetGrants?
|
718 |
+
$bucketLoggingStatus->appendChild($loggingEnabled);
|
719 |
+
}
|
720 |
+
$dom->appendChild($bucketLoggingStatus);
|
721 |
+
|
722 |
+
$rest = new iwpS3Request('PUT', $bucket, '', self::$endpoint);
|
723 |
+
$rest->setParameter('logging', null);
|
724 |
+
$rest->data = $dom->saveXML();
|
725 |
+
$rest->size = strlen($rest->data);
|
726 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
727 |
+
$rest = $rest->getResponse();
|
728 |
+
if ($rest->error === false && $rest->code !== 200)
|
729 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
730 |
+
if ($rest->error !== false)
|
731 |
+
{
|
732 |
+
self::__triggerError(sprintf("S3::setBucketLogging({$bucket}, {$uri}): [%s] %s",
|
733 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
734 |
+
return false;
|
735 |
+
}
|
736 |
+
return true;
|
737 |
+
}
|
738 |
+
|
739 |
+
|
740 |
+
/**
|
741 |
+
* Get logging status for a bucket
|
742 |
+
*
|
743 |
+
* This will return false if logging is not enabled.
|
744 |
+
* Note: To enable logging, you also need to grant write access to the log group
|
745 |
+
*
|
746 |
+
* @param string $bucket Bucket name
|
747 |
+
* @return array | false
|
748 |
+
*/
|
749 |
+
public static function getBucketLogging($bucket)
|
750 |
+
{
|
751 |
+
$rest = new iwpS3Request('GET', $bucket, '', self::$endpoint);
|
752 |
+
$rest->setParameter('logging', null);
|
753 |
+
$rest = $rest->getResponse();
|
754 |
+
if ($rest->error === false && $rest->code !== 200)
|
755 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
756 |
+
if ($rest->error !== false)
|
757 |
+
{
|
758 |
+
self::__triggerError(sprintf("S3::getBucketLogging({$bucket}): [%s] %s",
|
759 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
760 |
+
return false;
|
761 |
+
}
|
762 |
+
if (!isset($rest->body->LoggingEnabled)) return false; // No logging
|
763 |
+
return array(
|
764 |
+
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
|
765 |
+
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
|
766 |
+
);
|
767 |
+
}
|
768 |
+
|
769 |
+
|
770 |
+
/**
|
771 |
+
* Disable bucket logging
|
772 |
+
*
|
773 |
+
* @param string $bucket Bucket name
|
774 |
+
* @return boolean
|
775 |
+
*/
|
776 |
+
public static function disableBucketLogging($bucket)
|
777 |
+
{
|
778 |
+
return self::setBucketLogging($bucket, null);
|
779 |
+
}
|
780 |
+
|
781 |
+
|
782 |
+
/**
|
783 |
+
* Get a bucket's location
|
784 |
+
*
|
785 |
+
* @param string $bucket Bucket name
|
786 |
+
* @return string | false
|
787 |
+
*/
|
788 |
+
public static function getBucketLocation($bucket)
|
789 |
+
{
|
790 |
+
$rest = new iwpS3Request('GET', $bucket, '', self::$endpoint);
|
791 |
+
$rest->setParameter('location', null);
|
792 |
+
$rest = $rest->getResponse();
|
793 |
+
if ($rest->error === false && $rest->code !== 200)
|
794 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
795 |
+
if ($rest->error !== false)
|
796 |
+
{
|
797 |
+
self::__triggerError(sprintf("S3::getBucketLocation({$bucket}): [%s] %s",
|
798 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
799 |
+
return false;
|
800 |
+
}
|
801 |
+
return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
|
802 |
+
}
|
803 |
+
|
804 |
+
|
805 |
+
/**
|
806 |
+
* Set object or bucket Access Control Policy
|
807 |
+
*
|
808 |
+
* @param string $bucket Bucket name
|
809 |
+
* @param string $uri Object URI
|
810 |
+
* @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
|
811 |
+
* @return boolean
|
812 |
+
*/
|
813 |
+
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array())
|
814 |
+
{
|
815 |
+
$dom = new DOMDocument;
|
816 |
+
$dom->formatOutput = true;
|
817 |
+
$accessControlPolicy = $dom->createElement('AccessControlPolicy');
|
818 |
+
$accessControlList = $dom->createElement('AccessControlList');
|
819 |
+
|
820 |
+
// It seems the owner has to be passed along too
|
821 |
+
$owner = $dom->createElement('Owner');
|
822 |
+
$owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
|
823 |
+
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
|
824 |
+
$accessControlPolicy->appendChild($owner);
|
825 |
+
|
826 |
+
foreach ($acp['acl'] as $g)
|
827 |
+
{
|
828 |
+
$grant = $dom->createElement('Grant');
|
829 |
+
$grantee = $dom->createElement('Grantee');
|
830 |
+
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
831 |
+
if (isset($g['id']))
|
832 |
+
{ // CanonicalUser (DisplayName is omitted)
|
833 |
+
$grantee->setAttribute('xsi:type', 'CanonicalUser');
|
834 |
+
$grantee->appendChild($dom->createElement('ID', $g['id']));
|
835 |
+
}
|
836 |
+
elseif (isset($g['email']))
|
837 |
+
{ // AmazonCustomerByEmail
|
838 |
+
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
|
839 |
+
$grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
|
840 |
+
}
|
841 |
+
elseif ($g['type'] == 'Group')
|
842 |
+
{ // Group
|
843 |
+
$grantee->setAttribute('xsi:type', 'Group');
|
844 |
+
$grantee->appendChild($dom->createElement('URI', $g['uri']));
|
845 |
+
}
|
846 |
+
$grant->appendChild($grantee);
|
847 |
+
$grant->appendChild($dom->createElement('Permission', $g['permission']));
|
848 |
+
$accessControlList->appendChild($grant);
|
849 |
+
}
|
850 |
+
|
851 |
+
$accessControlPolicy->appendChild($accessControlList);
|
852 |
+
$dom->appendChild($accessControlPolicy);
|
853 |
+
|
854 |
+
$rest = new iwpS3Request('PUT', $bucket, $uri, self::$endpoint);
|
855 |
+
$rest->setParameter('acl', null);
|
856 |
+
$rest->data = $dom->saveXML();
|
857 |
+
$rest->size = strlen($rest->data);
|
858 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
859 |
+
$rest = $rest->getResponse();
|
860 |
+
if ($rest->error === false && $rest->code !== 200)
|
861 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
862 |
+
if ($rest->error !== false)
|
863 |
+
{
|
864 |
+
self::__triggerError(sprintf("S3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
865 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
866 |
+
return false;
|
867 |
+
}
|
868 |
+
return true;
|
869 |
+
}
|
870 |
+
|
871 |
+
|
872 |
+
/**
|
873 |
+
* Get object or bucket Access Control Policy
|
874 |
+
*
|
875 |
+
* @param string $bucket Bucket name
|
876 |
+
* @param string $uri Object URI
|
877 |
+
* @return mixed | false
|
878 |
+
*/
|
879 |
+
public static function getAccessControlPolicy($bucket, $uri = '')
|
880 |
+
{
|
881 |
+
$rest = new iwpS3Request('GET', $bucket, $uri, self::$endpoint);
|
882 |
+
$rest->setParameter('acl', null);
|
883 |
+
$rest = $rest->getResponse();
|
884 |
+
if ($rest->error === false && $rest->code !== 200)
|
885 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
886 |
+
if ($rest->error !== false)
|
887 |
+
{
|
888 |
+
self::__triggerError(sprintf("S3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
889 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
890 |
+
return false;
|
891 |
+
}
|
892 |
+
|
893 |
+
$acp = array();
|
894 |
+
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
|
895 |
+
$acp['owner'] = array(
|
896 |
+
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
|
897 |
+
);
|
898 |
+
|
899 |
+
if (isset($rest->body->AccessControlList))
|
900 |
+
{
|
901 |
+
$acp['acl'] = array();
|
902 |
+
foreach ($rest->body->AccessControlList->Grant as $grant)
|
903 |
+
{
|
904 |
+
foreach ($grant->Grantee as $grantee)
|
905 |
+
{
|
906 |
+
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
|
907 |
+
$acp['acl'][] = array(
|
908 |
+
'type' => 'CanonicalUser',
|
909 |
+
'id' => (string)$grantee->ID,
|
910 |
+
'name' => (string)$grantee->DisplayName,
|
911 |
+
'permission' => (string)$grant->Permission
|
912 |
+
);
|
913 |
+
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
|
914 |
+
$acp['acl'][] = array(
|
915 |
+
'type' => 'AmazonCustomerByEmail',
|
916 |
+
'email' => (string)$grantee->EmailAddress,
|
917 |
+
'permission' => (string)$grant->Permission
|
918 |
+
);
|
919 |
+
elseif (isset($grantee->URI)) // Group
|
920 |
+
$acp['acl'][] = array(
|
921 |
+
'type' => 'Group',
|
922 |
+
'uri' => (string)$grantee->URI,
|
923 |
+
'permission' => (string)$grant->Permission
|
924 |
+
);
|
925 |
+
else continue;
|
926 |
+
}
|
927 |
+
}
|
928 |
+
}
|
929 |
+
return $acp;
|
930 |
+
}
|
931 |
+
|
932 |
+
|
933 |
+
/**
|
934 |
+
* Delete an object
|
935 |
+
*
|
936 |
+
* @param string $bucket Bucket name
|
937 |
+
* @param string $uri Object URI
|
938 |
+
* @return boolean
|
939 |
+
*/
|
940 |
+
public static function deleteObject($bucket, $uri)
|
941 |
+
{
|
942 |
+
$rest = new iwpS3Request('DELETE', $bucket, $uri, self::$endpoint);
|
943 |
+
$rest = $rest->getResponse();
|
944 |
+
if ($rest->error === false && $rest->code !== 204)
|
945 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
946 |
+
if ($rest->error !== false)
|
947 |
+
{
|
948 |
+
self::__triggerError(sprintf("S3::deleteObject(): [%s] %s",
|
949 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
950 |
+
return false;
|
951 |
+
}
|
952 |
+
return true;
|
953 |
+
}
|
954 |
+
|
955 |
+
|
956 |
+
/**
|
957 |
+
* Get a query string authenticated URL
|
958 |
+
*
|
959 |
+
* @param string $bucket Bucket name
|
960 |
+
* @param string $uri Object URI
|
961 |
+
* @param integer $lifetime Lifetime in seconds
|
962 |
+
* @param boolean $hostBucket Use the bucket name as the hostname
|
963 |
+
* @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
|
964 |
+
* @return string
|
965 |
+
*/
|
966 |
+
public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false)
|
967 |
+
{
|
968 |
+
$expires = time() + $lifetime;
|
969 |
+
$uri = str_replace('%2F', '/', rawurlencode($uri)); // URI should be encoded (thanks Sean O'Dea)
|
970 |
+
return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
|
971 |
+
// $hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
|
972 |
+
$hostBucket ? $bucket : 's3.amazonaws.com/'.$bucket, $uri, self::$__accessKey, $expires,
|
973 |
+
urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
|
974 |
+
}
|
975 |
+
|
976 |
+
|
977 |
+
/**
|
978 |
+
* Get a CloudFront signed policy URL
|
979 |
+
*
|
980 |
+
* @param array $policy Policy
|
981 |
+
* @return string
|
982 |
+
*/
|
983 |
+
public static function getSignedPolicyURL($policy)
|
984 |
+
{
|
985 |
+
$data = json_encode($policy);
|
986 |
+
$signature = '';
|
987 |
+
if (!openssl_sign($data, $signature, self::$__signingKeyResource)) return false;
|
988 |
+
|
989 |
+
$encoded = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($data));
|
990 |
+
$signature = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($signature));
|
991 |
+
|
992 |
+
$url = $policy['Statement'][0]['Resource'] . '?';
|
993 |
+
foreach (array('Policy' => $encoded, 'Signature' => $signature, 'Key-Pair-Id' => self::$__signingKeyPairId) as $k => $v)
|
994 |
+
$url .= $k.'='.str_replace('%2F', '/', rawurlencode($v)).'&';
|
995 |
+
return substr($url, 0, -1);
|
996 |
+
}
|
997 |
+
|
998 |
+
|
999 |
+
/**
|
1000 |
+
* Get a CloudFront canned policy URL
|
1001 |
+
*
|
1002 |
+
* @param string $string URL to sign
|
1003 |
+
* @param integer $lifetime URL lifetime
|
1004 |
+
* @return string
|
1005 |
+
*/
|
1006 |
+
public static function getSignedCannedURL($url, $lifetime)
|
1007 |
+
{
|
1008 |
+
return self::getSignedPolicyURL(array(
|
1009 |
+
'Statement' => array(
|
1010 |
+
array('Resource' => $url, 'Condition' => array(
|
1011 |
+
'DateLessThan' => array('AWS:EpochTime' => time() + $lifetime)
|
1012 |
+
))
|
1013 |
+
)
|
1014 |
+
));
|
1015 |
+
}
|
1016 |
+
|
1017 |
+
|
1018 |
+
/**
|
1019 |
+
* Get upload POST parameters for form uploads
|
1020 |
+
*
|
1021 |
+
* @param string $bucket Bucket name
|
1022 |
+
* @param string $uriPrefix Object URI prefix
|
1023 |
+
* @param constant $acl ACL constant
|
1024 |
+
* @param integer $lifetime Lifetime in seconds
|
1025 |
+
* @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
|
1026 |
+
* @param string $successRedirect Redirect URL or 200 / 201 status code
|
1027 |
+
* @param array $amzHeaders Array of x-amz-meta-* headers
|
1028 |
+
* @param array $headers Array of request headers or content type as a string
|
1029 |
+
* @param boolean $flashVars Includes additional "Filename" variable posted by Flash
|
1030 |
+
* @return object
|
1031 |
+
*/
|
1032 |
+
public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600,
|
1033 |
+
$maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false)
|
1034 |
+
{
|
1035 |
+
// Create policy object
|
1036 |
+
$policy = new stdClass;
|
1037 |
+
$policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
|
1038 |
+
$policy->conditions = array();
|
1039 |
+
$obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
|
1040 |
+
$obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
|
1041 |
+
|
1042 |
+
$obj = new stdClass; // 200 for non-redirect uploads
|
1043 |
+
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
1044 |
+
$obj->success_action_status = (string)$successRedirect;
|
1045 |
+
else // URL
|
1046 |
+
$obj->success_action_redirect = $successRedirect;
|
1047 |
+
array_push($policy->conditions, $obj);
|
1048 |
+
|
1049 |
+
if ($acl !== self::ACL_PUBLIC_READ)
|
1050 |
+
array_push($policy->conditions, array('eq', '$acl', $acl));
|
1051 |
+
|
1052 |
+
array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
|
1053 |
+
if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
|
1054 |
+
foreach (array_keys($headers) as $headerKey)
|
1055 |
+
array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
|
1056 |
+
foreach ($amzHeaders as $headerKey => $headerVal)
|
1057 |
+
{
|
1058 |
+
$obj = new stdClass;
|
1059 |
+
$obj->{$headerKey} = (string)$headerVal;
|
1060 |
+
array_push($policy->conditions, $obj);
|
1061 |
+
}
|
1062 |
+
array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
|
1063 |
+
$policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
|
1064 |
+
|
1065 |
+
// Create parameters
|
1066 |
+
$params = new stdClass;
|
1067 |
+
$params->AWSAccessKeyId = self::$__accessKey;
|
1068 |
+
$params->key = $uriPrefix.'${filename}';
|
1069 |
+
$params->acl = $acl;
|
1070 |
+
$params->policy = $policy; unset($policy);
|
1071 |
+
$params->signature = self::__getHash($params->policy);
|
1072 |
+
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
1073 |
+
$params->success_action_status = (string)$successRedirect;
|
1074 |
+
else
|
1075 |
+
$params->success_action_redirect = $successRedirect;
|
1076 |
+
foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
1077 |
+
foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
1078 |
+
return $params;
|
1079 |
+
}
|
1080 |
+
|
1081 |
+
|
1082 |
+
/**
|
1083 |
+
* Create a CloudFront distribution
|
1084 |
+
*
|
1085 |
+
* @param string $bucket Bucket name
|
1086 |
+
* @param boolean $enabled Enabled (true/false)
|
1087 |
+
* @param array $cnames Array containing CNAME aliases
|
1088 |
+
* @param string $comment Use the bucket name as the hostname
|
1089 |
+
* @param string $defaultRootObject Default root object
|
1090 |
+
* @param string $originAccessIdentity Origin access identity
|
1091 |
+
* @param array $trustedSigners Array of trusted signers
|
1092 |
+
* @return array | false
|
1093 |
+
*/
|
1094 |
+
public static function createDistribution($bucket, $enabled = true, $cnames = array(), $comment = null, $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
|
1095 |
+
{
|
1096 |
+
if (!extension_loaded('openssl'))
|
1097 |
+
{
|
1098 |
+
self::__triggerError(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): %s",
|
1099 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1100 |
+
return false;
|
1101 |
+
}
|
1102 |
+
$useSSL = self::$useSSL;
|
1103 |
+
|
1104 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1105 |
+
$rest = new iwpS3Request('POST', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
|
1106 |
+
$rest->data = self::__getCloudFrontDistributionConfigXML(
|
1107 |
+
$bucket.'.s3.amazonaws.com',
|
1108 |
+
$enabled,
|
1109 |
+
(string)$comment,
|
1110 |
+
(string)microtime(true),
|
1111 |
+
$cnames,
|
1112 |
+
$defaultRootObject,
|
1113 |
+
$originAccessIdentity,
|
1114 |
+
$trustedSigners
|
1115 |
+
);
|
1116 |
+
|
1117 |
+
$rest->size = strlen($rest->data);
|
1118 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
1119 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1120 |
+
|
1121 |
+
self::$useSSL = $useSSL;
|
1122 |
+
|
1123 |
+
if ($rest->error === false && $rest->code !== 201)
|
1124 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1125 |
+
if ($rest->error !== false)
|
1126 |
+
{
|
1127 |
+
self::__triggerError(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): [%s] %s",
|
1128 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
1129 |
+
return false;
|
1130 |
+
} elseif ($rest->body instanceof SimpleXMLElement)
|
1131 |
+
return self::__parseCloudFrontDistributionConfig($rest->body);
|
1132 |
+
return false;
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
|
1136 |
+
/**
|
1137 |
+
* Get CloudFront distribution info
|
1138 |
+
*
|
1139 |
+
* @param string $distributionId Distribution ID from listDistributions()
|
1140 |
+
* @return array | false
|
1141 |
+
*/
|
1142 |
+
public static function getDistribution($distributionId)
|
1143 |
+
{
|
1144 |
+
if (!extension_loaded('openssl'))
|
1145 |
+
{
|
1146 |
+
self::__triggerError(sprintf("S3::getDistribution($distributionId): %s",
|
1147 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1148 |
+
return false;
|
1149 |
+
}
|
1150 |
+
$useSSL = self::$useSSL;
|
1151 |
+
|
1152 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1153 |
+
$rest = new iwpS3Request('GET', '', '2010-11-01/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
|
1154 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1155 |
+
|
1156 |
+
self::$useSSL = $useSSL;
|
1157 |
+
|
1158 |
+
if ($rest->error === false && $rest->code !== 200)
|
1159 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1160 |
+
if ($rest->error !== false)
|
1161 |
+
{
|
1162 |
+
self::__triggerError(sprintf("S3::getDistribution($distributionId): [%s] %s",
|
1163 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
1164 |
+
return false;
|
1165 |
+
}
|
1166 |
+
elseif ($rest->body instanceof SimpleXMLElement)
|
1167 |
+
{
|
1168 |
+
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
1169 |
+
$dist['hash'] = $rest->headers['hash'];
|
1170 |
+
$dist['id'] = $distributionId;
|
1171 |
+
return $dist;
|
1172 |
+
}
|
1173 |
+
return false;
|
1174 |
+
}
|
1175 |
+
|
1176 |
+
|
1177 |
+
/**
|
1178 |
+
* Update a CloudFront distribution
|
1179 |
+
*
|
1180 |
+
* @param array $dist Distribution array info identical to output of getDistribution()
|
1181 |
+
* @return array | false
|
1182 |
+
*/
|
1183 |
+
public static function updateDistribution($dist)
|
1184 |
+
{
|
1185 |
+
if (!extension_loaded('openssl'))
|
1186 |
+
{
|
1187 |
+
self::__triggerError(sprintf("S3::updateDistribution({$dist['id']}): %s",
|
1188 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1189 |
+
return false;
|
1190 |
+
}
|
1191 |
+
|
1192 |
+
$useSSL = self::$useSSL;
|
1193 |
+
|
1194 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1195 |
+
$rest = new iwpS3Request('PUT', '', '2010-11-01/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
|
1196 |
+
$rest->data = self::__getCloudFrontDistributionConfigXML(
|
1197 |
+
$dist['origin'],
|
1198 |
+
$dist['enabled'],
|
1199 |
+
$dist['comment'],
|
1200 |
+
$dist['callerReference'],
|
1201 |
+
$dist['cnames'],
|
1202 |
+
$dist['defaultRootObject'],
|
1203 |
+
$dist['originAccessIdentity'],
|
1204 |
+
$dist['trustedSigners']
|
1205 |
+
);
|
1206 |
+
|
1207 |
+
$rest->size = strlen($rest->data);
|
1208 |
+
$rest->setHeader('If-Match', $dist['hash']);
|
1209 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1210 |
+
|
1211 |
+
self::$useSSL = $useSSL;
|
1212 |
+
|
1213 |
+
if ($rest->error === false && $rest->code !== 200)
|
1214 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1215 |
+
if ($rest->error !== false)
|
1216 |
+
{
|
1217 |
+
self::__triggerError(sprintf("S3::updateDistribution({$dist['id']}): [%s] %s",
|
1218 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
1219 |
+
return false;
|
1220 |
+
} else {
|
1221 |
+
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
1222 |
+
$dist['hash'] = $rest->headers['hash'];
|
1223 |
+
return $dist;
|
1224 |
+
}
|
1225 |
+
return false;
|
1226 |
+
}
|
1227 |
+
|
1228 |
+
|
1229 |
+
/**
|
1230 |
+
* Delete a CloudFront distribution
|
1231 |
+
*
|
1232 |
+
* @param array $dist Distribution array info identical to output of getDistribution()
|
1233 |
+
* @return boolean
|
1234 |
+
*/
|
1235 |
+
public static function deleteDistribution($dist)
|
1236 |
+
{
|
1237 |
+
if (!extension_loaded('openssl'))
|
1238 |
+
{
|
1239 |
+
self::__triggerError(sprintf("S3::deleteDistribution({$dist['id']}): %s",
|
1240 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1241 |
+
return false;
|
1242 |
+
}
|
1243 |
+
|
1244 |
+
$useSSL = self::$useSSL;
|
1245 |
+
|
1246 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1247 |
+
$rest = new iwpS3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
|
1248 |
+
$rest->setHeader('If-Match', $dist['hash']);
|
1249 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1250 |
+
|
1251 |
+
self::$useSSL = $useSSL;
|
1252 |
+
|
1253 |
+
if ($rest->error === false && $rest->code !== 204)
|
1254 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1255 |
+
if ($rest->error !== false)
|
1256 |
+
{
|
1257 |
+
self::__triggerError(sprintf("S3::deleteDistribution({$dist['id']}): [%s] %s",
|
1258 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
1259 |
+
return false;
|
1260 |
+
}
|
1261 |
+
return true;
|
1262 |
+
}
|
1263 |
+
|
1264 |
+
|
1265 |
+
/**
|
1266 |
+
* Get a list of CloudFront distributions
|
1267 |
+
*
|
1268 |
+
* @return array
|
1269 |
+
*/
|
1270 |
+
public static function listDistributions()
|
1271 |
+
{
|
1272 |
+
if (!extension_loaded('openssl'))
|
1273 |
+
{
|
1274 |
+
self::__triggerError(sprintf("S3::listDistributions(): [%s] %s",
|
1275 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1276 |
+
return false;
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
$useSSL = self::$useSSL;
|
1280 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1281 |
+
$rest = new iwpS3Request('GET', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
|
1282 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1283 |
+
self::$useSSL = $useSSL;
|
1284 |
+
|
1285 |
+
if ($rest->error === false && $rest->code !== 200)
|
1286 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1287 |
+
if ($rest->error !== false)
|
1288 |
+
{
|
1289 |
+
self::__triggerError(sprintf("S3::listDistributions(): [%s] %s",
|
1290 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
1291 |
+
return false;
|
1292 |
+
}
|
1293 |
+
elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary))
|
1294 |
+
{
|
1295 |
+
$list = array();
|
1296 |
+
if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated))
|
1297 |
+
{
|
1298 |
+
//$info['marker'] = (string)$rest->body->Marker;
|
1299 |
+
//$info['maxItems'] = (int)$rest->body->MaxItems;
|
1300 |
+
//$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
|
1301 |
+
}
|
1302 |
+
foreach ($rest->body->DistributionSummary as $summary)
|
1303 |
+
$list[(string)$summary->Id] = self::__parseCloudFrontDistributionConfig($summary);
|
1304 |
+
|
1305 |
+
return $list;
|
1306 |
+
}
|
1307 |
+
return array();
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
/**
|
1311 |
+
* List CloudFront Origin Access Identities
|
1312 |
+
*
|
1313 |
+
* @return array
|
1314 |
+
*/
|
1315 |
+
public static function listOriginAccessIdentities()
|
1316 |
+
{
|
1317 |
+
if (!extension_loaded('openssl'))
|
1318 |
+
{
|
1319 |
+
self::__triggerError(sprintf("S3::listOriginAccessIdentities(): [%s] %s",
|
1320 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1321 |
+
return false;
|
1322 |
+
}
|
1323 |
+
|
1324 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1325 |
+
$rest = new iwpS3Request('GET', '', '2010-11-01/origin-access-identity/cloudfront', 'cloudfront.amazonaws.com');
|
1326 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1327 |
+
$useSSL = self::$useSSL;
|
1328 |
+
|
1329 |
+
if ($rest->error === false && $rest->code !== 200)
|
1330 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1331 |
+
if ($rest->error !== false)
|
1332 |
+
{
|
1333 |
+
trigger_error(sprintf("S3::listOriginAccessIdentities(): [%s] %s",
|
1334 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
1335 |
+
return false;
|
1336 |
+
}
|
1337 |
+
|
1338 |
+
if (isset($rest->body->CloudFrontOriginAccessIdentitySummary))
|
1339 |
+
{
|
1340 |
+
$identities = array();
|
1341 |
+
foreach ($rest->body->CloudFrontOriginAccessIdentitySummary as $identity)
|
1342 |
+
if (isset($identity->S3CanonicalUserId))
|
1343 |
+
$identities[(string)$identity->Id] = array('id' => (string)$identity->Id, 's3CanonicalUserId' => (string)$identity->S3CanonicalUserId);
|
1344 |
+
return $identities;
|
1345 |
+
}
|
1346 |
+
return false;
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
|
1350 |
+
/**
|
1351 |
+
* Invalidate objects in a CloudFront distribution
|
1352 |
+
*
|
1353 |
+
* Thanks to Martin Lindkvist for S3::invalidateDistribution()
|
1354 |
+
*
|
1355 |
+
* @param string $distributionId Distribution ID from listDistributions()
|
1356 |
+
* @param array $paths Array of object paths to invalidate
|
1357 |
+
* @return boolean
|
1358 |
+
*/
|
1359 |
+
public static function invalidateDistribution($distributionId, $paths)
|
1360 |
+
{
|
1361 |
+
if (!extension_loaded('openssl'))
|
1362 |
+
{
|
1363 |
+
self::__triggerError(sprintf("S3::invalidateDistribution(): [%s] %s",
|
1364 |
+
"CloudFront functionality requires SSL"), __FILE__, __LINE__);
|
1365 |
+
return false;
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
$useSSL = self::$useSSL;
|
1369 |
+
self::$useSSL = true; // CloudFront requires SSL
|
1370 |
+
$rest = new iwpS3Request('POST', '', '2010-08-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
|
1371 |
+
$rest->data = self::__getCloudFrontInvalidationBatchXML($paths, (string)microtime(true));
|
1372 |
+
$rest->size = strlen($rest->data);
|
1373 |
+
$rest = self::__getCloudFrontResponse($rest);
|
1374 |
+
self::$useSSL = $useSSL;
|
1375 |
+
|
1376 |
+
if ($rest->error === false && $rest->code !== 201)
|
1377 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
1378 |
+
if ($rest->error !== false)
|
1379 |
+
{
|
1380 |
+
trigger_error(sprintf("S3::invalidate('{$distributionId}',{$paths}): [%s] %s",
|
1381 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
1382 |
+
return false;
|
1383 |
+
}
|
1384 |
+
return true;
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
|
1388 |
+
/**
|
1389 |
+
* Get a InvalidationBatch DOMDocument
|
1390 |
+
*
|
1391 |
+
* @internal Used to create XML in invalidateDistribution()
|
1392 |
+
* @param array $paths Paths to objects to invalidateDistribution
|
1393 |
+
* @return string
|
1394 |
+
*/
|
1395 |
+
private static function __getCloudFrontInvalidationBatchXML($paths, $callerReference = '0') {
|
1396 |
+
$dom = new DOMDocument('1.0', 'UTF-8');
|
1397 |
+
$dom->formatOutput = true;
|
1398 |
+
$invalidationBatch = $dom->createElement('InvalidationBatch');
|
1399 |
+
foreach ($paths as $path)
|
1400 |
+
$invalidationBatch->appendChild($dom->createElement('Path', $path));
|
1401 |
+
|
1402 |
+
$invalidationBatch->appendChild($dom->createElement('CallerReference', $callerReference));
|
1403 |
+
$dom->appendChild($invalidationBatch);
|
1404 |
+
return $dom->saveXML();
|
1405 |
+
}
|
1406 |
+
|
1407 |
+
|
1408 |
+
/**
|
1409 |
+
* Get a DistributionConfig DOMDocument
|
1410 |
+
*
|
1411 |
+
* http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?PutConfig.html
|
1412 |
+
*
|
1413 |
+
* @internal Used to create XML in createDistribution() and updateDistribution()
|
1414 |
+
* @param string $bucket S3 Origin bucket
|
1415 |
+
* @param boolean $enabled Enabled (true/false)
|
1416 |
+
* @param string $comment Comment to append
|
1417 |
+
* @param string $callerReference Caller reference
|
1418 |
+
* @param array $cnames Array of CNAME aliases
|
1419 |
+
* @param string $defaultRootObject Default root object
|
1420 |
+
* @param string $originAccessIdentity Origin access identity
|
1421 |
+
* @param array $trustedSigners Array of trusted signers
|
1422 |
+
* @return string
|
1423 |
+
*/
|
1424 |
+
private static function __getCloudFrontDistributionConfigXML($bucket, $enabled, $comment, $callerReference = '0', $cnames = array(), $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
|
1425 |
+
{
|
1426 |
+
$dom = new DOMDocument('1.0', 'UTF-8');
|
1427 |
+
$dom->formatOutput = true;
|
1428 |
+
$distributionConfig = $dom->createElement('DistributionConfig');
|
1429 |
+
$distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2010-11-01/');
|
1430 |
+
|
1431 |
+
$origin = $dom->createElement('S3Origin');
|
1432 |
+
$origin->appendChild($dom->createElement('DNSName', $bucket));
|
1433 |
+
if ($originAccessIdentity !== null) $origin->appendChild($dom->createElement('OriginAccessIdentity', $originAccessIdentity));
|
1434 |
+
$distributionConfig->appendChild($origin);
|
1435 |
+
|
1436 |
+
if ($defaultRootObject !== null) $distributionConfig->appendChild($dom->createElement('DefaultRootObject', $defaultRootObject));
|
1437 |
+
|
1438 |
+
$distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
|
1439 |
+
foreach ($cnames as $cname)
|
1440 |
+
$distributionConfig->appendChild($dom->createElement('CNAME', $cname));
|
1441 |
+
if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
|
1442 |
+
$distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
|
1443 |
+
|
1444 |
+
$trusted = $dom->createElement('TrustedSigners');
|
1445 |
+
foreach ($trustedSigners as $id => $type)
|
1446 |
+
$trusted->appendChild($id !== '' ? $dom->createElement($type, $id) : $dom->createElement($type));
|
1447 |
+
$distributionConfig->appendChild($trusted);
|
1448 |
+
|
1449 |
+
$dom->appendChild($distributionConfig);
|
1450 |
+
//var_dump($dom->saveXML());
|
1451 |
+
return $dom->saveXML();
|
1452 |
+
}
|
1453 |
+
|
1454 |
+
|
1455 |
+
/**
|
1456 |
+
* Parse a CloudFront distribution config
|
1457 |
+
*
|
1458 |
+
* See http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?GetDistribution.html
|
1459 |
+
*
|
1460 |
+
* @internal Used to parse the CloudFront DistributionConfig node to an array
|
1461 |
+
* @param object &$node DOMNode
|
1462 |
+
* @return array
|
1463 |
+
*/
|
1464 |
+
private static function __parseCloudFrontDistributionConfig(&$node)
|
1465 |
+
{
|
1466 |
+
if (isset($node->DistributionConfig))
|
1467 |
+
return self::__parseCloudFrontDistributionConfig($node->DistributionConfig);
|
1468 |
+
|
1469 |
+
$dist = array();
|
1470 |
+
if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName))
|
1471 |
+
{
|
1472 |
+
$dist['id'] = (string)$node->Id;
|
1473 |
+
$dist['status'] = (string)$node->Status;
|
1474 |
+
$dist['time'] = strtotime((string)$node->LastModifiedTime);
|
1475 |
+
$dist['domain'] = (string)$node->DomainName;
|
1476 |
+
}
|
1477 |
+
|
1478 |
+
if (isset($node->CallerReference))
|
1479 |
+
$dist['callerReference'] = (string)$node->CallerReference;
|
1480 |
+
|
1481 |
+
if (isset($node->Enabled))
|
1482 |
+
$dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
|
1483 |
+
|
1484 |
+
if (isset($node->S3Origin))
|
1485 |
+
{
|
1486 |
+
if (isset($node->S3Origin->DNSName))
|
1487 |
+
$dist['origin'] = (string)$node->S3Origin->DNSName;
|
1488 |
+
|
1489 |
+
$dist['originAccessIdentity'] = isset($node->S3Origin->OriginAccessIdentity) ?
|
1490 |
+
(string)$node->S3Origin->OriginAccessIdentity : null;
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
$dist['defaultRootObject'] = isset($node->DefaultRootObject) ? (string)$node->DefaultRootObject : null;
|
1494 |
+
|
1495 |
+
$dist['cnames'] = array();
|
1496 |
+
if (isset($node->CNAME))
|
1497 |
+
foreach ($node->CNAME as $cname)
|
1498 |
+
$dist['cnames'][(string)$cname] = (string)$cname;
|
1499 |
+
|
1500 |
+
$dist['trustedSigners'] = array();
|
1501 |
+
if (isset($node->TrustedSigners))
|
1502 |
+
foreach ($node->TrustedSigners as $signer)
|
1503 |
+
{
|
1504 |
+
if (isset($signer->Self))
|
1505 |
+
$dist['trustedSigners'][''] = 'Self';
|
1506 |
+
elseif (isset($signer->KeyPairId))
|
1507 |
+
$dist['trustedSigners'][(string)$signer->KeyPairId] = 'KeyPairId';
|
1508 |
+
elseif (isset($signer->AwsAccountNumber))
|
1509 |
+
$dist['trustedSigners'][(string)$signer->AwsAccountNumber] = 'AwsAccountNumber';
|
1510 |
+
}
|
1511 |
+
|
1512 |
+
$dist['comment'] = isset($node->Comment) ? (string)$node->Comment : null;
|
1513 |
+
return $dist;
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
|
1517 |
+
/**
|
1518 |
+
* Grab CloudFront response
|
1519 |
+
*
|
1520 |
+
* @internal Used to parse the CloudFront S3Request::getResponse() output
|
1521 |
+
* @param object &$rest S3Request instance
|
1522 |
+
* @return object
|
1523 |
+
*/
|
1524 |
+
private static function __getCloudFrontResponse(&$rest)
|
1525 |
+
{
|
1526 |
+
$rest->getResponse();
|
1527 |
+
if ($rest->response->error === false && isset($rest->response->body) &&
|
1528 |
+
is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml')
|
1529 |
+
{
|
1530 |
+
$rest->response->body = simplexml_load_string($rest->response->body);
|
1531 |
+
// Grab CloudFront errors
|
1532 |
+
if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
|
1533 |
+
$rest->response->body->Error->Message))
|
1534 |
+
{
|
1535 |
+
$rest->response->error = array(
|
1536 |
+
'code' => (string)$rest->response->body->Error->Code,
|
1537 |
+
'message' => (string)$rest->response->body->Error->Message
|
1538 |
+
);
|
1539 |
+
unset($rest->response->body);
|
1540 |
+
}
|
1541 |
+
}
|
1542 |
+
return $rest->response;
|
1543 |
+
}
|
1544 |
+
|
1545 |
+
|
1546 |
+
/**
|
1547 |
+
* Get MIME type for file
|
1548 |
+
*
|
1549 |
+
* @internal Used to get mime types
|
1550 |
+
* @param string &$file File path
|
1551 |
+
* @return string
|
1552 |
+
*/
|
1553 |
+
public static function __getMimeType(&$file)
|
1554 |
+
{
|
1555 |
+
$type = false;
|
1556 |
+
// Fileinfo documentation says fileinfo_open() will use the
|
1557 |
+
// MAGIC env var for the magic file
|
1558 |
+
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
|
1559 |
+
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false)
|
1560 |
+
{
|
1561 |
+
if (($type = finfo_file($finfo, $file)) !== false)
|
1562 |
+
{
|
1563 |
+
// Remove the charset and grab the last content-type
|
1564 |
+
$type = explode(' ', str_replace('; charset=', ';charset=', $type));
|
1565 |
+
$type = array_pop($type);
|
1566 |
+
$type = explode(';', $type);
|
1567 |
+
$type = trim(array_shift($type));
|
1568 |
+
}
|
1569 |
+
finfo_close($finfo);
|
1570 |
+
|
1571 |
+
// If anyone is still using mime_content_type()
|
1572 |
+
} elseif (function_exists('mime_content_type'))
|
1573 |
+
$type = trim(mime_content_type($file));
|
1574 |
+
|
1575 |
+
if ($type !== false && strlen($type) > 0) return $type;
|
1576 |
+
|
1577 |
+
// Otherwise do it the old fashioned way
|
1578 |
+
static $exts = array(
|
1579 |
+
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
|
1580 |
+
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
|
1581 |
+
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
|
1582 |
+
'zip' => 'application/zip', 'gz' => 'application/x-gzip',
|
1583 |
+
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
|
1584 |
+
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
|
1585 |
+
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
|
1586 |
+
'css' => 'text/css', 'js' => 'text/javascript',
|
1587 |
+
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
|
1588 |
+
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
|
1589 |
+
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
|
1590 |
+
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
|
1591 |
+
);
|
1592 |
+
$ext = strtolower(pathInfo($file, PATHINFO_EXTENSION));
|
1593 |
+
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
|
1594 |
+
}
|
1595 |
+
|
1596 |
+
|
1597 |
+
/**
|
1598 |
+
* Generate the auth string: "AWS AccessKey:Signature"
|
1599 |
+
*
|
1600 |
+
* @internal Used by S3Request::getResponse()
|
1601 |
+
* @param string $string String to sign
|
1602 |
+
* @return string
|
1603 |
+
*/
|
1604 |
+
public static function __getSignature($string)
|
1605 |
+
{
|
1606 |
+
return 'AWS '.self::$__accessKey.':'.self::__getHash($string);
|
1607 |
+
}
|
1608 |
+
|
1609 |
+
|
1610 |
+
/**
|
1611 |
+
* Creates a HMAC-SHA1 hash
|
1612 |
+
*
|
1613 |
+
* This uses the hash extension if loaded
|
1614 |
+
*
|
1615 |
+
* @internal Used by __getSignature()
|
1616 |
+
* @param string $string String to sign
|
1617 |
+
* @return string
|
1618 |
+
*/
|
1619 |
+
private static function __getHash($string)
|
1620 |
+
{
|
1621 |
+
return base64_encode(extension_loaded('hash') ?
|
1622 |
+
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
|
1623 |
+
(str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
|
1624 |
+
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
|
1625 |
+
(str_repeat(chr(0x36), 64))) . $string)))));
|
1626 |
+
}
|
1627 |
+
|
1628 |
+
}
|
1629 |
+
|
1630 |
+
final class iwpS3Request
|
1631 |
+
{
|
1632 |
+
private $endpoint, $verb, $bucket, $uri, $resource = '', $parameters = array(),
|
1633 |
+
$amzHeaders = array(), $headers = array(
|
1634 |
+
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
|
1635 |
+
);
|
1636 |
+
public $fp = false, $size = 0, $data = false, $response;
|
1637 |
+
|
1638 |
+
|
1639 |
+
/**
|
1640 |
+
* Constructor
|
1641 |
+
*
|
1642 |
+
* @param string $verb Verb
|
1643 |
+
* @param string $bucket Bucket name
|
1644 |
+
* @param string $uri Object URI
|
1645 |
+
* @return mixed
|
1646 |
+
*/
|
1647 |
+
function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com')
|
1648 |
+
{
|
1649 |
+
$this->endpoint = $endpoint;
|
1650 |
+
$this->verb = $verb;
|
1651 |
+
$this->bucket = $bucket;
|
1652 |
+
$this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
|
1653 |
+
|
1654 |
+
//if ($this->bucket !== '')
|
1655 |
+
// $this->resource = '/'.$this->bucket.$this->uri;
|
1656 |
+
//else
|
1657 |
+
// $this->resource = $this->uri;
|
1658 |
+
|
1659 |
+
if ($this->bucket !== '')
|
1660 |
+
{
|
1661 |
+
if ($this->__dnsBucketName($this->bucket))
|
1662 |
+
{
|
1663 |
+
$this->headers['Host'] = $this->bucket.'.'.$this->endpoint;
|
1664 |
+
$this->resource = '/'.$this->bucket.$this->uri;
|
1665 |
+
}
|
1666 |
+
else
|
1667 |
+
{
|
1668 |
+
$this->headers['Host'] = $this->endpoint;
|
1669 |
+
$this->uri = $this->uri;
|
1670 |
+
if ($this->bucket !== '') $this->uri = '/'.$this->bucket.$this->uri;
|
1671 |
+
$this->bucket = '';
|
1672 |
+
$this->resource = $this->uri;
|
1673 |
+
}
|
1674 |
+
}
|
1675 |
+
else
|
1676 |
+
{
|
1677 |
+
$this->headers['Host'] = $this->endpoint;
|
1678 |
+
$this->resource = $this->uri;
|
1679 |
+
}
|
1680 |
+
|
1681 |
+
|
1682 |
+
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
|
1683 |
+
$this->response = new STDClass;
|
1684 |
+
$this->response->error = false;
|
1685 |
+
}
|
1686 |
+
|
1687 |
+
|
1688 |
+
/**
|
1689 |
+
* Set request parameter
|
1690 |
+
*
|
1691 |
+
* @param string $key Key
|
1692 |
+
* @param string $value Value
|
1693 |
+
* @return void
|
1694 |
+
*/
|
1695 |
+
public function setParameter($key, $value)
|
1696 |
+
{
|
1697 |
+
$this->parameters[$key] = $value;
|
1698 |
+
}
|
1699 |
+
|
1700 |
+
|
1701 |
+
/**
|
1702 |
+
* Set request header
|
1703 |
+
*
|
1704 |
+
* @param string $key Key
|
1705 |
+
* @param string $value Value
|
1706 |
+
* @return void
|
1707 |
+
*/
|
1708 |
+
public function setHeader($key, $value)
|
1709 |
+
{
|
1710 |
+
$this->headers[$key] = $value;
|
1711 |
+
}
|
1712 |
+
|
1713 |
+
|
1714 |
+
/**
|
1715 |
+
* Set x-amz-meta-* header
|
1716 |
+
*
|
1717 |
+
* @param string $key Key
|
1718 |
+
* @param string $value Value
|
1719 |
+
* @return void
|
1720 |
+
*/
|
1721 |
+
public function setAmzHeader($key, $value)
|
1722 |
+
{
|
1723 |
+
$this->amzHeaders[$key] = $value;
|
1724 |
+
}
|
1725 |
+
|
1726 |
+
|
1727 |
+
/**
|
1728 |
+
* Get the S3 response
|
1729 |
+
*
|
1730 |
+
* @return object | false
|
1731 |
+
*/
|
1732 |
+
public function getResponse()
|
1733 |
+
{
|
1734 |
+
$query = '';
|
1735 |
+
if (sizeof($this->parameters) > 0)
|
1736 |
+
{
|
1737 |
+
$query = substr($this->uri, -1) !== '?' ? '?' : '&';
|
1738 |
+
foreach ($this->parameters as $var => $value)
|
1739 |
+
if ($value == null || $value == '') $query .= $var.'&';
|
1740 |
+
// Parameters should be encoded (thanks Sean O'Dea)
|
1741 |
+
else $query .= $var.'='.rawurlencode($value).'&';
|
1742 |
+
$query = substr($query, 0, -1);
|
1743 |
+
$this->uri .= $query;
|
1744 |
+
|
1745 |
+
if (array_key_exists('acl', $this->parameters) ||
|
1746 |
+
array_key_exists('location', $this->parameters) ||
|
1747 |
+
array_key_exists('torrent', $this->parameters) ||
|
1748 |
+
array_key_exists('website', $this->parameters) ||
|
1749 |
+
array_key_exists('logging', $this->parameters))
|
1750 |
+
$this->resource .= $query;
|
1751 |
+
}
|
1752 |
+
$url = (S3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
|
1753 |
+
|
1754 |
+
//var_dump('bucket: ' . $this->bucket, 'uri: ' . $this->uri, 'resource: ' . $this->resource, 'url: ' . $url);
|
1755 |
+
|
1756 |
+
// Basic setup
|
1757 |
+
$curl = curl_init();
|
1758 |
+
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
|
1759 |
+
curl_setopt($curl,CURLOPT_TIMEOUT,600);
|
1760 |
+
if (S3::$useSSL)
|
1761 |
+
{
|
1762 |
+
// SSL Validation can now be optional for those with broken OpenSSL installations
|
1763 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, S3::$useSSLValidation ? 1 : 0);
|
1764 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, S3::$useSSLValidation ? 1 : 0);
|
1765 |
+
|
1766 |
+
if (S3::$sslKey !== null) curl_setopt($curl, CURLOPT_SSLKEY, S3::$sslKey);
|
1767 |
+
if (S3::$sslCert !== null) curl_setopt($curl, CURLOPT_SSLCERT, S3::$sslCert);
|
1768 |
+
if (S3::$sslCACert !== null) curl_setopt($curl, CURLOPT_CAINFO, S3::$sslCACert);
|
1769 |
+
}
|
1770 |
+
|
1771 |
+
curl_setopt($curl, CURLOPT_URL, $url);
|
1772 |
+
|
1773 |
+
if (S3::$proxy != null && isset(S3::$proxy['host']))
|
1774 |
+
{
|
1775 |
+
curl_setopt($curl, CURLOPT_PROXY, S3::$proxy['host']);
|
1776 |
+
curl_setopt($curl, CURLOPT_PROXYTYPE, S3::$proxy['type']);
|
1777 |
+
if (isset(S3::$proxy['user'], S3::$proxy['pass']) && $proxy['user'] != null && $proxy['pass'] != null)
|
1778 |
+
curl_setopt($curl, CURLOPT_PROXYUSERPWD, sprintf('%s:%s', S3::$proxy['user'], S3::$proxy['pass']));
|
1779 |
+
}
|
1780 |
+
|
1781 |
+
// Headers
|
1782 |
+
$headers = array(); $amz = array();
|
1783 |
+
foreach ($this->amzHeaders as $header => $value)
|
1784 |
+
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1785 |
+
foreach ($this->headers as $header => $value)
|
1786 |
+
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1787 |
+
|
1788 |
+
// Collect AMZ headers for signature
|
1789 |
+
foreach ($this->amzHeaders as $header => $value)
|
1790 |
+
if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
|
1791 |
+
|
1792 |
+
// AMZ headers must be sorted
|
1793 |
+
if (sizeof($amz) > 0)
|
1794 |
+
{
|
1795 |
+
sort($amz);
|
1796 |
+
$amz = "\n".implode("\n", $amz);
|
1797 |
+
} else $amz = '';
|
1798 |
+
|
1799 |
+
if (S3::hasAuth())
|
1800 |
+
{
|
1801 |
+
// Authorization string (CloudFront stringToSign should only contain a date)
|
1802 |
+
if ($this->headers['Host'] == 'cloudfront.amazonaws.com')
|
1803 |
+
$headers[] = 'Authorization: ' . S3::__getSignature($this->headers['Date']);
|
1804 |
+
else
|
1805 |
+
{
|
1806 |
+
$headers[] = 'Authorization: ' . S3::__getSignature(
|
1807 |
+
$this->verb."\n".
|
1808 |
+
$this->headers['Content-MD5']."\n".
|
1809 |
+
$this->headers['Content-Type']."\n".
|
1810 |
+
$this->headers['Date'].$amz."\n".
|
1811 |
+
$this->resource
|
1812 |
+
);
|
1813 |
+
}
|
1814 |
+
}
|
1815 |
+
|
1816 |
+
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
1817 |
+
curl_setopt($curl, CURLOPT_HEADER, false);
|
1818 |
+
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
|
1819 |
+
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
|
1820 |
+
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
|
1821 |
+
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
1822 |
+
|
1823 |
+
// Request types
|
1824 |
+
switch ($this->verb)
|
1825 |
+
{
|
1826 |
+
case 'GET': break;
|
1827 |
+
case 'PUT': case 'POST': // POST only used for CloudFront
|
1828 |
+
if ($this->fp !== false)
|
1829 |
+
{
|
1830 |
+
curl_setopt($curl, CURLOPT_PUT, true);
|
1831 |
+
curl_setopt($curl, CURLOPT_INFILE, $this->fp);
|
1832 |
+
if ($this->size >= 0)
|
1833 |
+
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
|
1834 |
+
}
|
1835 |
+
elseif ($this->data !== false)
|
1836 |
+
{
|
1837 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1838 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
|
1839 |
+
}
|
1840 |
+
else
|
1841 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1842 |
+
break;
|
1843 |
+
case 'HEAD':
|
1844 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
|
1845 |
+
curl_setopt($curl, CURLOPT_NOBODY, true);
|
1846 |
+
break;
|
1847 |
+
case 'DELETE':
|
1848 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
1849 |
+
break;
|
1850 |
+
default: break;
|
1851 |
+
}
|
1852 |
+
|
1853 |
+
// Execute, grab errors
|
1854 |
+
if (curl_exec($curl))
|
1855 |
+
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
1856 |
+
else
|
1857 |
+
$this->response->error = array(
|
1858 |
+
'code' => curl_errno($curl),
|
1859 |
+
'message' => curl_error($curl),
|
1860 |
+
'resource' => $this->resource
|
1861 |
+
);
|
1862 |
+
|
1863 |
+
@curl_close($curl);
|
1864 |
+
|
1865 |
+
// Parse body into XML
|
1866 |
+
if ($this->response->error === false && isset($this->response->headers['type']) &&
|
1867 |
+
$this->response->headers['type'] == 'application/xml' && isset($this->response->body))
|
1868 |
+
{
|
1869 |
+
$this->response->body = simplexml_load_string($this->response->body);
|
1870 |
+
|
1871 |
+
// Grab S3 errors
|
1872 |
+
if (!in_array($this->response->code, array(200, 204, 206)) &&
|
1873 |
+
isset($this->response->body->Code, $this->response->body->Message))
|
1874 |
+
{
|
1875 |
+
$this->response->error = array(
|
1876 |
+
'code' => (string)$this->response->body->Code,
|
1877 |
+
'message' => (string)$this->response->body->Message
|
1878 |
+
);
|
1879 |
+
if (isset($this->response->body->Resource))
|
1880 |
+
$this->response->error['resource'] = (string)$this->response->body->Resource;
|
1881 |
+
unset($this->response->body);
|
1882 |
+
}
|
1883 |
+
}
|
1884 |
+
|
1885 |
+
// Clean up file resources
|
1886 |
+
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
|
1887 |
+
|
1888 |
+
return $this->response;
|
1889 |
+
}
|
1890 |
+
|
1891 |
+
|
1892 |
+
/**
|
1893 |
+
* CURL write callback
|
1894 |
+
*
|
1895 |
+
* @param resource &$curl CURL resource
|
1896 |
+
* @param string &$data Data
|
1897 |
+
* @return integer
|
1898 |
+
*/
|
1899 |
+
private function __responseWriteCallback(&$curl, &$data)
|
1900 |
+
{
|
1901 |
+
if (in_array($this->response->code, array(200, 206)) && $this->fp !== false)
|
1902 |
+
return fwrite($this->fp, $data);
|
1903 |
+
else
|
1904 |
+
$this->response->body .= $data;
|
1905 |
+
return strlen($data);
|
1906 |
+
}
|
1907 |
+
|
1908 |
+
|
1909 |
+
/**
|
1910 |
+
* Check DNS conformity
|
1911 |
+
*
|
1912 |
+
* @param string $bucket Bucket name
|
1913 |
+
* @return boolean
|
1914 |
+
*/
|
1915 |
+
private function __dnsBucketName($bucket)
|
1916 |
+
{
|
1917 |
+
if (strlen($bucket) > 63 || !preg_match("/[^a-z0-9\.-]/", $bucket)) return false;
|
1918 |
+
if (strstr($bucket, '-.') !== false) return false;
|
1919 |
+
if (strstr($bucket, '..') !== false) return false;
|
1920 |
+
if (!preg_match("/^[0-9a-z]/", $bucket)) return false;
|
1921 |
+
if (!preg_match("/[0-9a-z]$/", $bucket)) return false;
|
1922 |
+
return true;
|
1923 |
+
}
|
1924 |
+
|
1925 |
+
|
1926 |
+
/**
|
1927 |
+
* CURL header callback
|
1928 |
+
*
|
1929 |
+
* @param resource &$curl CURL resource
|
1930 |
+
* @param string &$data Data
|
1931 |
+
* @return integer
|
1932 |
+
*/
|
1933 |
+
private function __responseHeaderCallback(&$curl, &$data)
|
1934 |
+
{
|
1935 |
+
if (($strlen = strlen($data)) <= 2) return $strlen;
|
1936 |
+
if (substr($data, 0, 4) == 'HTTP')
|
1937 |
+
$this->response->code = (int)substr($data, 9, 3);
|
1938 |
+
else
|
1939 |
+
{
|
1940 |
+
$data = trim($data);
|
1941 |
+
if (strpos($data, ': ') === false) return $strlen;
|
1942 |
+
list($header, $value) = explode(': ', $data, 2);
|
1943 |
+
if ($header == 'Last-Modified')
|
1944 |
+
$this->response->headers['time'] = strtotime($value);
|
1945 |
+
elseif ($header == 'Content-Length')
|
1946 |
+
$this->response->headers['size'] = (int)$value;
|
1947 |
+
elseif ($header == 'Content-Type')
|
1948 |
+
$this->response->headers['type'] = $value;
|
1949 |
+
elseif ($header == 'ETag')
|
1950 |
+
$this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
|
1951 |
+
elseif (preg_match('/^x-amz-meta-.*$/', $header))
|
1952 |
+
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
|
1953 |
+
}
|
1954 |
+
return $strlen;
|
1955 |
+
}
|
1956 |
+
|
1957 |
+
}
|
1958 |
+
|
1959 |
+
class mwpS3Exception extends Exception {
|
1960 |
+
function __construct($message, $file, $line, $code = 0)
|
1961 |
+
{
|
1962 |
+
parent::__construct($message, $code);
|
1963 |
+
$this->file = $file;
|
1964 |
+
$this->line = $line;
|
1965 |
+
}
|
1966 |
+
}
|
readme.txt
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
Contributors: infinitewp
|
3 |
Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multisite, multiple, notification, performance, s3, security, seo, stats, tracking, infinitewp, updates, backup, restore, iwp, infinite
|
4 |
Requires at least: 3.0
|
5 |
-
Tested up to: 3.
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Install this plugin on unlimited sites and manage them all from a central dashboard.
|
@@ -22,11 +22,14 @@ Main features:
|
|
22 |
* Bulk Install plugins & themes in multiple sites at once
|
23 |
* and more..
|
24 |
|
|
|
|
|
25 |
Check out the [InfiniteWP Overview Video](http://www.youtube.com/watch?v=IOu7LdyPOSs) below.
|
26 |
|
27 |
http://www.youtube.com/watch?v=IOu7LdyPOSs
|
28 |
|
29 |
-
|
|
|
30 |
|
31 |
== Installation ==
|
32 |
|
@@ -45,6 +48,11 @@ Check out [InfiniteWP.com](http://infinitewp.com/ "Manage Multiple WordPress").
|
|
45 |
|
46 |
== Changelog ==
|
47 |
|
|
|
|
|
|
|
|
|
|
|
48 |
= 1.0.3 =
|
49 |
* WordPress Multisite Backup issue fixed
|
50 |
* Bugs fixed
|
2 |
Contributors: infinitewp
|
3 |
Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multisite, multiple, notification, performance, s3, security, seo, stats, tracking, infinitewp, updates, backup, restore, iwp, infinite
|
4 |
Requires at least: 3.0
|
5 |
+
Tested up to: 3.4.1
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Install this plugin on unlimited sites and manage them all from a central dashboard.
|
22 |
* Bulk Install plugins & themes in multiple sites at once
|
23 |
* and more..
|
24 |
|
25 |
+
Visit us at [InfiniteWP.com](http://infinitewp.com/ "Manage Multiple WordPress").
|
26 |
+
|
27 |
Check out the [InfiniteWP Overview Video](http://www.youtube.com/watch?v=IOu7LdyPOSs) below.
|
28 |
|
29 |
http://www.youtube.com/watch?v=IOu7LdyPOSs
|
30 |
|
31 |
+
Credits: [Vladimir Prelovac](http://prelovac.com/vladimir) for his worker plugin on which the client plugin is being developed.
|
32 |
+
|
33 |
|
34 |
== Installation ==
|
35 |
|
48 |
|
49 |
== Changelog ==
|
50 |
|
51 |
+
= 1.0.4 =
|
52 |
+
* Premium addons compatibility
|
53 |
+
* Clearing cache and sending WP data
|
54 |
+
* Bugs fixed
|
55 |
+
|
56 |
= 1.0.3 =
|
57 |
* WordPress Multisite Backup issue fixed
|
58 |
* Bugs fixed
|
stats.class.php
CHANGED
@@ -256,18 +256,22 @@ class IWP_MMB_Stats extends IWP_MMB_Core
|
|
256 |
function get_updates($stats, $options = array())
|
257 |
{
|
258 |
$upgrades = false;
|
259 |
-
|
260 |
if (isset($options['premium']) && $options['premium']) {
|
261 |
$premium_updates = array();
|
262 |
-
$upgrades = apply_filters('
|
263 |
if (!empty($upgrades)) {
|
|
|
|
|
|
|
|
|
264 |
$stats['premium_updates'] = $upgrades;
|
265 |
$upgrades = false;
|
266 |
}
|
267 |
}
|
268 |
if (isset($options['themes']) && $options['themes']) {
|
269 |
$this->get_installer_instance();
|
270 |
-
$upgrades = $this->installer_instance->get_upgradable_themes();
|
271 |
if (!empty($upgrades)) {
|
272 |
$stats['upgradable_themes'] = $upgrades;
|
273 |
$upgrades = false;
|
@@ -276,7 +280,7 @@ class IWP_MMB_Stats extends IWP_MMB_Core
|
|
276 |
|
277 |
if (isset($options['plugins']) && $options['plugins']) {
|
278 |
$this->get_installer_instance();
|
279 |
-
$upgrades = $this->installer_instance->get_upgradable_plugins();
|
280 |
if (!empty($upgrades)) {
|
281 |
$stats['upgradable_plugins'] = $upgrades;
|
282 |
$upgrades = false;
|
@@ -349,8 +353,16 @@ class IWP_MMB_Stats extends IWP_MMB_Core
|
|
349 |
|
350 |
$stats = $this->iwp_mmb_parse_action_params('pre_init_stats', $params, $this);
|
351 |
$num = extract($params);
|
352 |
-
|
353 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
$current = $this->iwp_mmb_get_transient('update_core');
|
355 |
if (isset($current->last_checked) || get_option('iwp_client_forcerefresh')) {
|
356 |
update_option('iwp_client_forcerefresh', false);
|
@@ -400,7 +412,7 @@ class IWP_MMB_Stats extends IWP_MMB_Core
|
|
400 |
$update_check = array();
|
401 |
$num = extract($params);
|
402 |
if ($refresh == 'transient') {
|
403 |
-
$update_check = apply_filters('
|
404 |
if (!empty($update_check)) {
|
405 |
foreach ($update_check as $update) {
|
406 |
if (is_array($update['callback'])) {
|
256 |
function get_updates($stats, $options = array())
|
257 |
{
|
258 |
$upgrades = false;
|
259 |
+
$premium = array();
|
260 |
if (isset($options['premium']) && $options['premium']) {
|
261 |
$premium_updates = array();
|
262 |
+
$upgrades = apply_filters('mwp_premium_update_notification', $premium_updates);
|
263 |
if (!empty($upgrades)) {
|
264 |
+
foreach( $upgrades as $data ){
|
265 |
+
if( isset($data['Name']) )
|
266 |
+
$premium[] = $data['Name'];
|
267 |
+
}
|
268 |
$stats['premium_updates'] = $upgrades;
|
269 |
$upgrades = false;
|
270 |
}
|
271 |
}
|
272 |
if (isset($options['themes']) && $options['themes']) {
|
273 |
$this->get_installer_instance();
|
274 |
+
$upgrades = $this->installer_instance->get_upgradable_themes( $premium );
|
275 |
if (!empty($upgrades)) {
|
276 |
$stats['upgradable_themes'] = $upgrades;
|
277 |
$upgrades = false;
|
280 |
|
281 |
if (isset($options['plugins']) && $options['plugins']) {
|
282 |
$this->get_installer_instance();
|
283 |
+
$upgrades = $this->installer_instance->get_upgradable_plugins( $premium );
|
284 |
if (!empty($upgrades)) {
|
285 |
$stats['upgradable_plugins'] = $upgrades;
|
286 |
$upgrades = false;
|
353 |
|
354 |
$stats = $this->iwp_mmb_parse_action_params('pre_init_stats', $params, $this);
|
355 |
$num = extract($params);
|
356 |
+
|
357 |
+
if (function_exists( 'w3tc_pgcache_flush' ) || function_exists( 'wp_cache_clear_cache' ) || !empty($force_refresh)) {
|
358 |
+
$this->iwp_mmb_delete_transient('update_plugins');
|
359 |
+
@wp_update_plugins();
|
360 |
+
$this->iwp_mmb_delete_transient('update_themes');
|
361 |
+
@wp_update_themes();
|
362 |
+
$this->iwp_mmb_delete_transient('update_core');
|
363 |
+
@wp_version_check();
|
364 |
+
}
|
365 |
+
elseif ($refresh == 'transient') {
|
366 |
$current = $this->iwp_mmb_get_transient('update_core');
|
367 |
if (isset($current->last_checked) || get_option('iwp_client_forcerefresh')) {
|
368 |
update_option('iwp_client_forcerefresh', false);
|
412 |
$update_check = array();
|
413 |
$num = extract($params);
|
414 |
if ($refresh == 'transient') {
|
415 |
+
$update_check = apply_filters('mwp_premium_update_check', $update_check);
|
416 |
if (!empty($update_check)) {
|
417 |
foreach ($update_check as $update) {
|
418 |
if (is_array($update['callback'])) {
|