Version Description
- Backup file size now in log file
- Paged Logs Table
- added Backup Archives Page
- Grammar fixes
- Bug fixes
Download this release
Release Info
Developer | danielhuesken |
Plugin | BackWPup – WordPress Backup Plugin |
Version | 1.2.0 |
Comparing to | |
See all releases |
Code changes from version 1.1.1 to 1.2.0
- app/backwpup_dojob.php +196 -183
- app/css/options.css +11 -11
- app/functions.php +228 -104
- app/libs/S3.php +1365 -1365
- app/options-backups.php +165 -0
- app/options-logs.php +59 -24
- app/options-runnow.php +1 -0
- app/options-save.php +105 -2
- app/options-settings.php +1 -0
- app/options-tools.php +1 -0
- app/options-view_log.php +1 -0
- app/options.php +1 -0
- backwpup.php +57 -57
- readme.txt +53 -46
app/backwpup_dojob.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
<?php
|
2 |
-
// don't load directly
|
3 |
-
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
|
6 |
-
|
7 |
-
//function for PHP error handling
|
8 |
function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
|
9 |
global $backwpup_logfile;
|
10 |
-
|
11 |
//genrate timestamp
|
12 |
if (!function_exists('memory_get_usage')) { // test if memory functions compiled in
|
13 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
14 |
} else {
|
15 |
if (version_compare(phpversion(), '5.2.0', '<'))
|
16 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage())."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage())."|Mem Limit: ".ini_get('memory_limit')."]\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
17 |
-
else
|
18 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage(true))."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage(true))."|Mem Limit: ".ini_get('memory_limit')."]\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
19 |
}
|
20 |
-
|
21 |
switch ($errno) {
|
22 |
case E_NOTICE:
|
23 |
case E_USER_NOTICE:
|
@@ -36,7 +36,7 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
|
|
36 |
break;
|
37 |
case E_DEPRECATED:
|
38 |
case E_USER_DEPRECATED:
|
39 |
-
$massage=$timestamp."<span>".__('[DEPRECATED]','backwpup')." ".$errstr."</span>";
|
40 |
break;
|
41 |
case E_STRICT:
|
42 |
$massage=$timestamp."<span>".__('[STRICT NOTICE]','backwpup')." ".$errstr."</span>";
|
@@ -48,20 +48,20 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
|
|
48 |
$massage=$timestamp."<span>[".$errno."] ".$errstr."</span>";
|
49 |
break;
|
50 |
}
|
51 |
-
|
52 |
if (!empty($massage)) {
|
53 |
//wirte log file
|
54 |
$fd=@fopen($backwpup_logfile,"a+");
|
55 |
@fputs($fd,$massage."<br />\n");
|
56 |
@fclose($fd);
|
57 |
-
|
58 |
-
//output on run now
|
59 |
if (!defined('DOING_CRON')) {
|
60 |
echo $massage."<script type=\"text/javascript\">window.scrollBy(0, 15);</script><br />\n";
|
61 |
@flush();
|
62 |
@ob_flush();
|
63 |
}
|
64 |
-
|
65 |
//write new log header
|
66 |
if (isset($errors) or isset($warnings)) {
|
67 |
$fd=@fopen($backwpup_logfile,"r+");
|
@@ -81,10 +81,10 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
|
|
81 |
}
|
82 |
@fclose($fd);
|
83 |
}
|
84 |
-
|
85 |
if ($errno==E_ERROR or $errno==E_CORE_ERROR or $errno==E_COMPILE_ERROR) //Die on fatal php errors.
|
86 |
die();
|
87 |
-
|
88 |
|
89 |
@set_time_limit(300); //300 is most webserver time limit. 0= max time! Give script 5 min. more to work.
|
90 |
//true for no more php error hadling.
|
@@ -100,29 +100,29 @@ function backwpup_jobshutdown() {
|
|
100 |
$logheader=backwpup_read_logheader($backwpup_logfile); //read waring count from log header
|
101 |
$cfg=get_option('backwpup'); //load config
|
102 |
$jobs=get_option('backwpup_jobs'); //load job options
|
103 |
-
|
104 |
if (!empty($jobs[$logheader['jobid']]['stoptime'])) //abort if job exits normaly
|
105 |
return;
|
106 |
-
|
107 |
-
backwpup_joberrorhandler(E_USER_WARNING, __('Job shutdown function is working! Please delete temp
|
108 |
-
|
109 |
//try to get last error
|
110 |
$lasterror=error_get_last();
|
111 |
backwpup_joberrorhandler($lasterror['type'], __('Last ERROR:','backwpup').' '.$lasterror['message'], $lasterror['file'], $lasterror['line']);
|
112 |
-
|
113 |
//set Temp Dir
|
114 |
$tempdir=trailingslashit($cfg['dirtemp']);
|
115 |
-
if ($tempdir=='/')
|
116 |
$tempdir=backwpup_get_upload_dir();
|
117 |
-
|
118 |
if (is_file($tempdir.DB_NAME.'.sql') ) { //delete sql temp file
|
119 |
unlink($tempdir.DB_NAME.'.sql');
|
120 |
}
|
121 |
-
|
122 |
if (is_file($tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml') ) { //delete WP XML Export temp file
|
123 |
unlink($tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml');
|
124 |
}
|
125 |
-
|
126 |
$jobs[$logheader['jobid']]['stoptime']=current_time('timestamp');
|
127 |
$jobs[$logheader['jobid']]['lastrun']=$jobs[$logheader['jobid']]['starttime'];
|
128 |
$jobs[$logheader['jobid']]['lastruntime']=$jobs[$logheader['jobid']]['stoptime']-$jobs[$logheader['jobid']]['starttime'];
|
@@ -155,12 +155,12 @@ function backwpup_jobshutdown() {
|
|
155 |
if ($sendmail) {
|
156 |
$mailbody=__("Jobname:","backwpup")." ".$logdata['name']."\n";
|
157 |
$mailbody.=__("Jobtype:","backwpup")." ".$logdata['type']."\n";
|
158 |
-
if (!empty($logdata['errors']))
|
159 |
$mailbody.=__("Errors:","backwpup")." ".$logdata['errors']."\n";
|
160 |
if (!empty($logdata['warnings']))
|
161 |
$mailbody.=__("Warnings:","backwpup")." ".$logdata['warnings']."\n";
|
162 |
wp_mail($jobs[$logheader['jobid']]['mailaddresslog'],__('BackWPup Log File from','backwpup').' '.date_i18n('Y-m-d H:i',$jobs[$logheader['jobid']]['starttime']).': '.$jobs[$logheader['jobid']]['name'] ,$mailbody,'',array($backwpup_logfile));
|
163 |
-
}
|
164 |
}
|
165 |
|
166 |
/**
|
@@ -168,7 +168,7 @@ function backwpup_jobshutdown() {
|
|
168 |
*
|
169 |
*/
|
170 |
class backwpup_dojob {
|
171 |
-
|
172 |
private $jobid=0;
|
173 |
private $filelist=array();
|
174 |
private $tempfilelist=array();
|
@@ -182,7 +182,7 @@ class backwpup_dojob {
|
|
182 |
private $tempdir='';
|
183 |
private $cfg=array();
|
184 |
private $job=array();
|
185 |
-
|
186 |
public function __construct($jobid) {
|
187 |
global $backwpup_logfile,$backwpup_dojob;
|
188 |
@ini_get('safe_mode','Off'); //disable safe mode
|
@@ -204,7 +204,7 @@ class backwpup_dojob {
|
|
204 |
$this->backupfileformat=$this->job['fileformart'];
|
205 |
//set Temp Dir
|
206 |
$this->tempdir=trailingslashit($this->cfg['dirtemp']);
|
207 |
-
if (empty($this->tempdir) or $this->tempdir=='/')
|
208 |
$this->tempdir=backwpup_get_upload_dir();
|
209 |
//set Backup Dir
|
210 |
$this->backupdir=$this->job['backupdir'];
|
@@ -217,10 +217,10 @@ class backwpup_dojob {
|
|
217 |
$this->logdir=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'backwpup-'.$rand.'-logs/';
|
218 |
}
|
219 |
//set Backup file name only for jos that makes backups
|
220 |
-
if (in_array('FILE',$this->todo) or in_array('DB',$this->todo) or in_array('WPEXP',$this->todo))
|
221 |
$this->backupfile='backwpup_'.$this->jobid.'_'.date_i18n('Y-m-d_H-i-s').$this->backupfileformat;
|
222 |
//set Log file name
|
223 |
-
$this->logfile='backwpup_log_'.date_i18n('Y-m-d_H-i-s').'.html';
|
224 |
$backwpup_logfile=$this->logdir.$this->logfile;
|
225 |
//Create log file
|
226 |
if (!$this->_check_folders($this->logdir))
|
@@ -234,15 +234,16 @@ class backwpup_dojob {
|
|
234 |
@fputs($fd,"<meta name=\"backwpup_jobid\" content=\"".$this->jobid."\" />\n");
|
235 |
@fputs($fd,"<meta name=\"backwpup_jobname\" content=\"".$this->job['name']."\" />\n");
|
236 |
@fputs($fd,"<meta name=\"backwpup_jobtype\" content=\"".$this->job['type']."\" />\n");
|
237 |
-
if (!empty($this->backupfile)
|
238 |
-
@fputs($fd,"<meta name=\"backwpup_backupfile\" content=\"".$this->
|
|
|
239 |
@fputs($fd,str_pad("<meta name=\"backwpup_jobruntime\" content=\"0\" />",100)."\n");
|
240 |
@fputs($fd,"<title>".sprintf(__('BackWPup Log for %1$s from %2$s at %3$s','backwpup'),$this->job['name'],date_i18n(get_option('date_format')),date_i18n(get_option('time_format')))."</title>\n</head>\n<body style=\"font-family:monospace;font-size:12px;white-space:nowrap;\">\n");
|
241 |
@fclose($fd);
|
242 |
//set function for PHP user defineid error handling
|
243 |
if (defined(WP_DEBUG) and WP_DEBUG)
|
244 |
set_error_handler('backwpup_joberrorhandler',E_ALL | E_STRICT);
|
245 |
-
else
|
246 |
set_error_handler('backwpup_joberrorhandler',E_ALL & ~E_NOTICE);
|
247 |
//set a schutdown function.
|
248 |
register_shutdown_function('backwpup_jobshutdown');
|
@@ -252,12 +253,12 @@ class backwpup_dojob {
|
|
252 |
return false;
|
253 |
}
|
254 |
//check max script execution tme
|
255 |
-
if (ini_get('safe_mode') or strtolower(ini_get('safe_mode'))=='on' or ini_get('safe_mode')=='1')
|
256 |
trigger_error(sprintf(__('PHP Safe Mode is on!!! Max exec time is %1$d sec.','backwpup'),ini_get('max_execution_time')),E_USER_WARNING);
|
257 |
// check function for memorylimit
|
258 |
if (!function_exists('memory_get_usage')) {
|
259 |
ini_set('memory_limit', apply_filters( 'admin_memory_limit', '256M' )); //Wordpress default
|
260 |
-
trigger_error(sprintf(__('Memory limit set to %1$s ,because can not use PHP: memory_get_usage() function to
|
261 |
}
|
262 |
//run job parts
|
263 |
foreach($this->todo as $key => $value) {
|
@@ -280,13 +281,13 @@ class backwpup_dojob {
|
|
280 |
elseif ($this->backupfileformat==".tar.gz" or $this->backupfileformat==".tar.bz2" or $this->backupfileformat==".tar")
|
281 |
$this->tar_pack_files();
|
282 |
}
|
283 |
-
if (
|
284 |
$this->destination_mail();
|
285 |
$this->destination_ftp();
|
286 |
$this->destination_s3();
|
287 |
$this->destination_dir();
|
288 |
}
|
289 |
-
|
290 |
foreach($this->todo as $key => $value) {
|
291 |
switch ($value) {
|
292 |
case 'CHECK':
|
@@ -296,9 +297,9 @@ class backwpup_dojob {
|
|
296 |
$this->optimize_db();
|
297 |
break;
|
298 |
}
|
299 |
-
}
|
300 |
-
}
|
301 |
-
|
302 |
private function _check_folders($folder) {
|
303 |
if (!is_dir($folder)) { //create dir if not exists
|
304 |
if (!mkdir($folder,0777,true)) {
|
@@ -307,8 +308,8 @@ class backwpup_dojob {
|
|
307 |
}
|
308 |
}
|
309 |
if (!is_writeable($folder)) { //test if folder wirteable
|
310 |
-
trigger_error(sprintf(__('Can not write to Folder: %1$s','backwpup'),$folder),E_USER_ERROR);
|
311 |
-
return false;
|
312 |
}
|
313 |
//create .htaccess for apache and index.html for other
|
314 |
if (strtolower(substr($_SERVER["SERVER_SOFTWARE"],0,6))=="apache") { //check if it a apache webserver
|
@@ -323,18 +324,18 @@ class backwpup_dojob {
|
|
323 |
if($file = fopen($folder.'index.html', 'w')) {
|
324 |
fwrite($file,"\n");
|
325 |
fclose($file);
|
326 |
-
}
|
327 |
}
|
328 |
if (!is_file($folder.'index.php')) {
|
329 |
if($file = fopen($folder.'index.php', 'w')) {
|
330 |
fwrite($file,"\n");
|
331 |
fclose($file);
|
332 |
-
}
|
333 |
}
|
334 |
}
|
335 |
return true;
|
336 |
}
|
337 |
-
|
338 |
private function need_free_memory($memneed) {
|
339 |
//fail back if fuction not exist
|
340 |
if (!function_exists('memory_get_usage'))
|
@@ -344,7 +345,7 @@ class backwpup_dojob {
|
|
344 |
trigger_error(sprintf(__('PHP Safe Mode is on!!! Can not increase Memory Limit is %1$s','backwpup'),ini_get('memory_limit')),E_USER_WARNING);
|
345 |
return false;
|
346 |
}
|
347 |
-
|
348 |
//calc mem to bytes
|
349 |
if (strtoupper(substr(trim(ini_get('memory_limit')),-1))=='K')
|
350 |
$memory=trim(substr(ini_get('memory_limit'),0,-1))*1024;
|
@@ -354,73 +355,73 @@ class backwpup_dojob {
|
|
354 |
$memory=trim(substr(ini_get('memory_limit'),0,-1))*1024*1024*1024;
|
355 |
else
|
356 |
$memory=trim(ini_get('memory_limit'));
|
357 |
-
|
358 |
//use real memory at php version 5.2.0
|
359 |
if (version_compare(phpversion(), '5.2.0', '<'))
|
360 |
$memnow=memory_get_usage();
|
361 |
-
else
|
362 |
$memnow=memory_get_usage(true);
|
363 |
-
|
364 |
//need memory
|
365 |
$needmemory=$memnow+$memneed;
|
366 |
-
|
367 |
-
// increase Memory
|
368 |
-
if ($needmemory>$memory) {
|
369 |
$newmemory=round($needmemory/1024/1024)+1;
|
370 |
-
if ($oldmem=ini_set('memory_limit', $newmemory.'M'))
|
371 |
trigger_error(sprintf(__('Memory increased from %1$s to %2$s','backwpup'),$oldmem,ini_get('memory_limit')),E_USER_NOTICE);
|
372 |
-
else
|
373 |
trigger_error(sprintf(__('Can not increase Memory Limit is %1$s','backwpup'),ini_get('memory_limit')),E_USER_WARNING);
|
374 |
}
|
375 |
-
return true;
|
376 |
}
|
377 |
-
|
378 |
private function maintenance_mode($enable = false) {
|
379 |
if (!$this->job['maintenance'])
|
380 |
return;
|
381 |
-
|
382 |
if ( $enable ) {
|
383 |
trigger_error(__('Set Blog to Maintenance Mode','backwpup'),E_USER_NOTICE);
|
384 |
if ( class_exists('WPMaintenanceMode') ) { //Support for WP Maintenance Mode Plugin
|
385 |
-
update_option('wp-maintenance-mode-msqld','1');
|
386 |
} elseif ( class_exists('MaintenanceMode') ) { //Support for Maintenance Mode Plugin
|
387 |
$mamo=get_option('plugin_maintenance-mode');
|
388 |
$mamo['mamo_activate']='on_'.current_time('timestamp');
|
389 |
$mamo['mamo_backtime_days']='0';
|
390 |
$mamo['mamo_backtime_hours']='0';
|
391 |
$mamo['mamo_backtime_mins']='5';
|
392 |
-
update_option('plugin_maintenance-mode',$mamo);
|
393 |
} else { //WP Support
|
394 |
$fdmain=fopen(trailingslashit(ABSPATH).'.maintenance','w');
|
395 |
fputs($fdmain,'<?php $upgrading = ' . time() . '; ?>');
|
396 |
-
fclose($fdmain);
|
397 |
}
|
398 |
} else {
|
399 |
trigger_error(__('Set Blog to normal Mode','backwpup'),E_USER_NOTICE);
|
400 |
if ( class_exists('WPMaintenanceMode') ) { //Support for WP Maintenance Mode Plugin
|
401 |
-
update_option('wp-maintenance-mode-msqld','0');
|
402 |
} elseif ( class_exists('MaintenanceMode') ) { //Support for Maintenance Mode Plugin
|
403 |
$mamo=get_option('plugin_maintenance-mode');
|
404 |
$mamo['mamo_activate']='off';
|
405 |
-
update_option('plugin_maintenance-mode',$mamo);
|
406 |
} else { //WP Support
|
407 |
@unlink(trailingslashit(ABSPATH).'.maintenance');
|
408 |
}
|
409 |
}
|
410 |
}
|
411 |
-
|
412 |
private function check_db() {
|
413 |
global $wpdb;
|
414 |
-
|
415 |
trigger_error(__('Run Database check...','backwpup'),E_USER_NOTICE);
|
416 |
-
|
417 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
418 |
//exclude tables from check
|
419 |
foreach($tables as $tablekey => $tablevalue) {
|
420 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
421 |
unset($tables[$tablekey]);
|
422 |
}
|
423 |
-
|
424 |
//check tables
|
425 |
if (sizeof($tables)>0) {
|
426 |
$this->maintenance_mode(true);
|
@@ -431,8 +432,8 @@ class backwpup_dojob {
|
|
431 |
elseif ($check['Msg_type']=='warning')
|
432 |
trigger_error(sprintf(__('Result of table check for %1$s is: %2$s','backwpup'), $table, $check['Msg_text']),E_USER_WARNING);
|
433 |
else
|
434 |
-
trigger_error(sprintf(__('Result of table check for %1$s is: %2$s','backwpup'), $table, $check['Msg_text']),E_USER_NOTICE);
|
435 |
-
|
436 |
if ($sqlerr=mysql_error($wpdb->dbh)) //aditional SQL error
|
437 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
438 |
//Try to Repair tabele
|
@@ -443,8 +444,8 @@ class backwpup_dojob {
|
|
443 |
elseif ($repair['Msg_type']=='warning')
|
444 |
trigger_error(sprintf(__('Result of table repair for %1$s is: %2$s','backwpup'), $table, $repair['Msg_text']),E_USER_WARNING);
|
445 |
else
|
446 |
-
trigger_error(sprintf(__('Result of table repair for %1$s is: %2$s','backwpup'), $table, $repair['Msg_text']),E_USER_NOTICE);
|
447 |
-
|
448 |
if ($sqlerr=mysql_error($wpdb->dbh)) //aditional SQL error
|
449 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
450 |
}
|
@@ -454,7 +455,7 @@ class backwpup_dojob {
|
|
454 |
trigger_error(__('Database check done!','backwpup'),E_USER_NOTICE);
|
455 |
} else {
|
456 |
trigger_error(__('No Tables to check','backwpup'),E_USER_WARNING);
|
457 |
-
}
|
458 |
}
|
459 |
|
460 |
private function dump_db_table($table,$status,$file) {
|
@@ -464,7 +465,7 @@ class backwpup_dojob {
|
|
464 |
fwrite($file, "--\n");
|
465 |
fwrite($file, "-- Table structure for table $table\n");
|
466 |
fwrite($file, "--\n\n");
|
467 |
-
fwrite($file, "DROP TABLE IF EXISTS `" . $table . "`;\n");
|
468 |
fwrite($file, "/*!40101 SET @saved_cs_client = @@character_set_client */;\n");
|
469 |
fwrite($file, "/*!40101 SET character_set_client = '".mysql_client_encoding()."' */;\n");
|
470 |
//Dump the table structure
|
@@ -476,14 +477,14 @@ class backwpup_dojob {
|
|
476 |
$tablestruc=mysql_fetch_assoc($result);
|
477 |
fwrite($file, $tablestruc['Create Table'].";\n");
|
478 |
fwrite($file, "/*!40101 SET character_set_client = @saved_cs_client */;\n");
|
479 |
-
|
480 |
//take data of table
|
481 |
$result=mysql_query("SELECT * FROM `".$table."`");
|
482 |
if (!$result) {
|
483 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), mysql_error(), "SELECT * FROM `".$table."`"),E_USER_ERROR);
|
484 |
return false;
|
485 |
}
|
486 |
-
|
487 |
fwrite($file, "--\n");
|
488 |
fwrite($file, "-- Dumping data for table $table\n");
|
489 |
fwrite($file, "--\n\n");
|
@@ -491,7 +492,7 @@ class backwpup_dojob {
|
|
491 |
if ($status['Engine']=='MyISAM')
|
492 |
fwrite($file, "/*!40000 ALTER TABLE `".$table."` DISABLE KEYS */;\n");
|
493 |
|
494 |
-
|
495 |
while ($data = mysql_fetch_assoc($result)) {
|
496 |
$keys = array();
|
497 |
$values = array();
|
@@ -522,22 +523,22 @@ class backwpup_dojob {
|
|
522 |
global $wpdb;
|
523 |
trigger_error(__('Run Database Dump to file...','backwpup'),E_USER_NOTICE);
|
524 |
$this->maintenance_mode(true);
|
525 |
-
|
526 |
-
//Tables to backup
|
527 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
528 |
-
if ($sqlerr=mysql_error($wpdb->dbh))
|
529 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, "SHOW TABLES FROM `'.DB_NAME.'`"),E_USER_ERROR);
|
530 |
-
|
531 |
foreach($tables as $tablekey => $tablevalue) {
|
532 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
533 |
unset($tables[$tablekey]);
|
534 |
}
|
535 |
sort($tables);
|
536 |
-
|
537 |
|
538 |
if (sizeof($tables)>0) {
|
539 |
$result=$wpdb->get_results("SHOW TABLE STATUS FROM `".DB_NAME."`;", ARRAY_A); //get table status
|
540 |
-
if ($sqlerr=mysql_error($wpdb->dbh))
|
541 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, "SHOW TABLE STATUS FROM `".DB_NAME."`;"),E_USER_ERROR);
|
542 |
foreach($result as $statusdata) {
|
543 |
$status[$statusdata['Name']]=$statusdata;
|
@@ -549,9 +550,9 @@ class backwpup_dojob {
|
|
549 |
fwrite($file, "-- Plugin for WordPress by Daniel Huesken\n");
|
550 |
fwrite($file, "-- http://danielhuesken.de/portfolio/backwpup/\n");
|
551 |
fwrite($file, "-- Blog Name: ".get_option('blogname')."\n");
|
552 |
-
if (defined('WP_SITEURL'))
|
553 |
fwrite($file, "-- Blog URL: ".trailingslashit(WP_SITEURL)."\n");
|
554 |
-
else
|
555 |
fwrite($file, "-- Blog URL: ".trailingslashit(get_option('siteurl'))."\n");
|
556 |
fwrite($file, "-- Blog ABSPATH: ".trailingslashit(ABSPATH)."\n");
|
557 |
fwrite($file, "-- Table Prefix: ".$wpdb->prefix."\n");
|
@@ -598,9 +599,11 @@ class backwpup_dojob {
|
|
598 |
trigger_error(__('Add Database Dump to Backup:','backwpup').' '.DB_NAME.'.sql '.backwpup_formatBytes(filesize($this->tempdir.DB_NAME.'.sql')),E_USER_NOTICE);
|
599 |
$this->allfilesize+=filesize($this->tempdir.DB_NAME.'.sql');
|
600 |
$this->filelist[]=array(79001=>$this->tempdir.DB_NAME.'.sql',79003=>DB_NAME.'.sql');
|
601 |
-
|
602 |
$this->maintenance_mode(false);
|
603 |
-
}
|
|
|
|
|
604 |
|
605 |
private function export_wp() {
|
606 |
trigger_error(__('Run Wordpress Export to XML file...','backwpup'),E_USER_NOTICE);
|
@@ -613,20 +616,20 @@ class backwpup_dojob {
|
|
613 |
} else {
|
614 |
trigger_error(__('Can not Export to XML!','backwpup'),E_USER_ERROR);
|
615 |
}
|
616 |
-
}
|
617 |
|
618 |
private function optimize_db() {
|
619 |
global $wpdb;
|
620 |
-
|
621 |
trigger_error(__('Run Database optimize...','backwpup'),E_USER_NOTICE);
|
622 |
-
|
623 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
624 |
//exclude tables from optimize
|
625 |
foreach($tables as $tablekey => $tablevalue) {
|
626 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
627 |
unset($tables[$tablekey]);
|
628 |
}
|
629 |
-
|
630 |
if (sizeof($tables)>0) {
|
631 |
$this->maintenance_mode(true);
|
632 |
foreach ($tables as $table) {
|
@@ -636,9 +639,9 @@ class backwpup_dojob {
|
|
636 |
elseif ($optimize['Msg_type']=='warning')
|
637 |
trigger_error(sprintf(__('Result of table optimize for %1$s is: %2$s','backwpup'), $table, $optimize['Msg_text']),E_USER_WARNING);
|
638 |
else
|
639 |
-
trigger_error(sprintf(__('Result of table optimize for %1$s is: %2$s','backwpup'), $table, $optimize['Msg_text']),E_USER_NOTICE);
|
640 |
-
|
641 |
-
if ($sqlerr=mysql_error($wpdb->dbh))
|
642 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
643 |
}
|
644 |
$wpdb->flush();
|
@@ -646,7 +649,7 @@ class backwpup_dojob {
|
|
646 |
$this->maintenance_mode(false);
|
647 |
} else {
|
648 |
trigger_error(__('No Tables to optimize','backwpup'),E_USER_WARNING);
|
649 |
-
}
|
650 |
}
|
651 |
|
652 |
private function _file_list_folder( $folder = '', $levels = 100, $excludes,$excludedirs=array()) {
|
@@ -677,41 +680,41 @@ class backwpup_dojob {
|
|
677 |
}
|
678 |
}
|
679 |
@closedir( $dir );
|
680 |
-
}
|
681 |
}
|
682 |
-
|
683 |
private function file_list() {
|
684 |
|
685 |
//Make filelist
|
686 |
trigger_error(__('Make a list of files to Backup ....','backwpup'),E_USER_NOTICE);
|
687 |
-
|
688 |
$this->tempfilelist=array();
|
689 |
-
|
690 |
$backwpup_exclude=explode(',',trim($this->job['fileexclude']));
|
691 |
//Exclude Temp Files
|
692 |
$backwpup_exclude[]=$this->tempdir.DB_NAME.'.sql';
|
693 |
$backwpup_exclude[]=$this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml';
|
694 |
$backwpup_exclude=array_unique($backwpup_exclude,SORT_STRING);
|
695 |
-
|
696 |
//File list for blog folders
|
697 |
if ($this->job['backuproot'])
|
698 |
-
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',ABSPATH)),100,$backwpup_exclude,array_merge($this->job['backuprootexcludedirs'],backwpup_get_exclude_wp_dirs(ABSPATH)));
|
699 |
if ($this->job['backupcontent'])
|
700 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',WP_CONTENT_DIR)),100,$backwpup_exclude,array_merge($this->job['backupcontentexcludedirs'],backwpup_get_exclude_wp_dirs(WP_CONTENT_DIR)));
|
701 |
if ($this->job['backupplugins'])
|
702 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',WP_PLUGIN_DIR)),100,$backwpup_exclude,array_merge($this->job['backuppluginsexcludedirs'],backwpup_get_exclude_wp_dirs(WP_PLUGIN_DIR)));
|
703 |
-
if ($this->job['backupthemes'])
|
704 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',trailingslashit(WP_CONTENT_DIR).'themes')),100,$backwpup_exclude,array_merge($this->job['backupthemesexcludedirs'],backwpup_get_exclude_wp_dirs(trailingslashit(WP_CONTENT_DIR).'themes')));
|
705 |
if ($this->job['backupuploads'])
|
706 |
$this->_file_list_folder(untrailingslashit(backwpup_get_upload_dir()),100,$backwpup_exclude,array_merge($this->job['backupuploadsexcludedirs'],backwpup_get_exclude_wp_dirs(backwpup_get_upload_dir())));
|
707 |
-
|
708 |
-
//include dirs
|
709 |
$dirinclude=explode(',',$this->job['dirinclude']);
|
710 |
$dirinclude=array_unique($dirinclude,SORT_STRING);
|
711 |
//Crate file list
|
712 |
if (is_array($dirinclude)) {
|
713 |
foreach($dirinclude as $dirincludevalue) {
|
714 |
-
if (is_dir($dirincludevalue))
|
715 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',$dirincludevalue)),100,$backwpup_exclude);
|
716 |
}
|
717 |
}
|
@@ -722,22 +725,22 @@ class backwpup_dojob {
|
|
722 |
$this->filelist[]=array(79001=>$files,79003=>str_replace(str_replace('\\','/',trailingslashit(ABSPATH)),'',$files));
|
723 |
}
|
724 |
$this->tempfilelist=array();
|
725 |
-
|
726 |
if (!is_array($this->filelist[0])) {
|
727 |
trigger_error(__('No files to Backup','backwpup'),E_USER_ERROR);
|
728 |
} else {
|
729 |
trigger_error(__('Size off all files:','backwpup').' '.backwpup_formatBytes($this->allfilesize),E_USER_NOTICE);
|
730 |
}
|
731 |
-
|
732 |
-
}
|
733 |
|
734 |
private function zip_files() {
|
735 |
-
|
736 |
if (class_exists('ZipArchive')) { //use php zip lib
|
737 |
trigger_error(__('Create Backup Zip file...','backwpup'),E_USER_NOTICE);
|
738 |
$zip = new ZipArchive;
|
739 |
if ($res=$zip->open($this->backupdir.$this->backupfile,ZIPARCHIVE::CREATE) === TRUE) {
|
740 |
-
foreach($this->filelist as $key => $files) {
|
741 |
if (!is_file($files[79001])) //check file exists
|
742 |
continue;
|
743 |
if ($zip->addFile($files[79001], $files[79003])) {
|
@@ -751,31 +754,31 @@ class backwpup_dojob {
|
|
751 |
} else {
|
752 |
trigger_error(__('Can not create Backup ZIP file:','backwpup').' '.$res,E_USER_ERROR);
|
753 |
}
|
754 |
-
|
755 |
} else { //use PclZip
|
756 |
define( 'PCLZIP_TEMPORARY_DIR', $this->tempdir );
|
757 |
-
if (!class_exists('PclZip'))
|
758 |
require_once (plugin_dir_path(__FILE__).'libs/pclzip.lib.php');
|
759 |
-
|
760 |
//Create Zip File
|
761 |
if (is_array($this->filelist[0])) {
|
762 |
$this->need_free_memory(10485760); //10MB free memory for zip
|
763 |
trigger_error(__('Create Backup Zip (PclZip) file...','backwpup'),E_USER_NOTICE);
|
764 |
foreach($this->filelist as $key => $files) {
|
765 |
trigger_error(__('Add File to ZIP file:','backwpup').' '.$files[79001].' '.backwpup_formatBytes(filesize($files[79001])),E_USER_NOTICE);
|
766 |
-
}
|
767 |
$zipbackupfile = new PclZip($this->backupdir.$this->backupfile);
|
768 |
if (0==$zipbackupfile -> create($this->filelist,PCLZIP_OPT_ADD_TEMP_FILE_ON)) {
|
769 |
trigger_error(__('Zip file create:','backwpup').' '.$zipbackupfile->errorInfo(true),E_USER_ERROR);
|
770 |
-
} else {
|
771 |
trigger_error(__('Backup Zip file create done!','backwpup'),E_USER_NOTICE);
|
772 |
}
|
773 |
}
|
774 |
}
|
775 |
}
|
776 |
-
|
777 |
private function tar_pack_files() {
|
778 |
-
|
779 |
if ($this->backupfileformat=='.tar.gz') {
|
780 |
$tarbackup=gzopen($this->backupdir.$this->backupfile,'w9');
|
781 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
@@ -783,23 +786,23 @@ class backwpup_dojob {
|
|
783 |
} else {
|
784 |
$tarbackup=fopen($this->backupdir.$this->backupfile,'w');
|
785 |
}
|
786 |
-
|
787 |
if (!$tarbackup) {
|
788 |
trigger_error(__('Can not create TAR Backup file','backwpup'),E_USER_ERROR);
|
789 |
return;
|
790 |
} else {
|
791 |
trigger_error(__('Create Backup Archive file...','backwpup'),E_USER_NOTICE);
|
792 |
}
|
793 |
-
|
794 |
$this->need_free_memory(1048576); //1MB free memory for zip
|
795 |
-
|
796 |
foreach($this->filelist as $key => $files) {
|
797 |
trigger_error(__('Add File to Backup Archive:','backwpup').' '.$files[79001].' '.backwpup_formatBytes(filesize($files[79001])),E_USER_NOTICE);
|
798 |
-
|
799 |
//check file exists
|
800 |
if (!is_file($files[79001]))
|
801 |
continue;
|
802 |
-
|
803 |
// Get file information
|
804 |
$file_information = stat($files[79001]);
|
805 |
|
@@ -822,15 +825,15 @@ class backwpup_dojob {
|
|
822 |
"", //device minor number 8
|
823 |
substr($files[79003],101), //prefix for file name 155
|
824 |
""); //fill block 512K
|
825 |
-
|
826 |
// Computes the unsigned Checksum of a file's header
|
827 |
$checksum = 0;
|
828 |
for ($i = 0; $i < 512; $i++)
|
829 |
$checksum += ord(substr($header, $i, 1));
|
830 |
$checksum = pack("a8", sprintf("%07o", $checksum));
|
831 |
-
|
832 |
$header = substr_replace($header, $checksum, 148, 8);
|
833 |
-
|
834 |
if ($this->backupfileformat=='.tar.gz') {
|
835 |
gzwrite($tarbackup, $header);
|
836 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
@@ -838,7 +841,7 @@ class backwpup_dojob {
|
|
838 |
} else {
|
839 |
fwrite($tarbackup, $header);
|
840 |
}
|
841 |
-
|
842 |
// read/write files in 512K Blocks
|
843 |
$fd=fopen($files[79001],'rb');
|
844 |
while(!feof($fd)) {
|
@@ -855,23 +858,23 @@ class backwpup_dojob {
|
|
855 |
}
|
856 |
fclose($fd);
|
857 |
}
|
858 |
-
|
859 |
-
|
860 |
if ($this->backupfileformat=='.tar.gz') {
|
861 |
gzwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
862 |
-
gzclose($tarbackup);
|
863 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
864 |
bzwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
865 |
bzclose($tarbackup);
|
866 |
} else {
|
867 |
fwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
868 |
-
fclose($tarbackup);
|
869 |
}
|
870 |
-
|
871 |
trigger_error(__('Backup Archive file create done!','backwpup'),E_USER_NOTICE);
|
872 |
}
|
873 |
-
|
874 |
-
|
875 |
private function _ftp_raw_helper($ftp_conn_id,$command) { //FTP Comands helper function
|
876 |
$return=ftp_raw($ftp_conn_id,$command);
|
877 |
if (strtoupper(substr(trim($command),0,4))=="PASS") {
|
@@ -899,13 +902,13 @@ class backwpup_dojob {
|
|
899 |
}
|
900 |
}
|
901 |
}
|
902 |
-
|
903 |
-
|
904 |
private function destination_ftp() {
|
905 |
-
|
906 |
-
if (empty($this->job['ftphost']) or empty($this->job['ftpuser']) or empty($this->job['ftppass']))
|
907 |
return false;
|
908 |
-
|
909 |
$ftpport=21;
|
910 |
$ftphost=$this->job['ftphost'];
|
911 |
if (false !== strpos($this->job['ftphost'],':')) //look for port
|
@@ -913,17 +916,15 @@ class backwpup_dojob {
|
|
913 |
|
914 |
if (function_exists('ftp_ssl_connect')) { //make SSL FTP connection
|
915 |
$ftp_conn_id = ftp_ssl_connect($ftphost,$ftpport,10);
|
916 |
-
if ($ftp_conn_id)
|
917 |
trigger_error(__('Connected by SSL to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_NOTICE);
|
918 |
-
}
|
919 |
}
|
920 |
if (!$ftp_conn_id) { //make normal FTP conection if SSL not work
|
921 |
$ftp_conn_id = ftp_connect($ftphost,$ftpport,10);
|
922 |
-
if ($ftp_conn_id)
|
923 |
trigger_error(__('Connected insecure to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_NOTICE);
|
924 |
-
}
|
925 |
}
|
926 |
-
|
927 |
if (!$ftp_conn_id) {
|
928 |
trigger_error(__('Can not connect to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_ERROR);
|
929 |
return false;
|
@@ -941,45 +942,45 @@ class backwpup_dojob {
|
|
941 |
}
|
942 |
}
|
943 |
}
|
944 |
-
|
945 |
//if (ftp_login($ftp_conn_id, $jobs[$jobid]['ftpuser'], $jobs[$jobid]['ftppass'])) {
|
946 |
-
if (!$loginok)
|
947 |
return false;
|
948 |
-
|
949 |
//SYSTYPE
|
950 |
$this->_ftp_raw_helper($ftp_conn_id,'SYST');
|
951 |
//PASV
|
952 |
trigger_error(__('FTP Client command:','backwpup').' PASV',E_USER_NOTICE);
|
953 |
if (ftp_pasv($ftp_conn_id, true))
|
954 |
trigger_error(__('Server Completion reply: 227 Entering Passive Mode','backwpup'),E_USER_NOTICE);
|
955 |
-
else
|
956 |
trigger_error(__('FTP Server reply:','backwpup').' '.__('Can not Entering Passive Mode','backwpup'),E_USER_WARNING);
|
957 |
//ALLO show no erros in log if do not work
|
958 |
trigger_error(__('FTP Client command:','backwpup').' ALLO',E_USER_NOTICE);
|
959 |
ftp_alloc($ftp_conn_id,filesize($this->backupdir.$this->backupfile),$result);
|
960 |
trigger_error(__('FTP Server reply:','backwpup').' '.$result,E_USER_NOTICE);
|
961 |
-
|
962 |
//test ftp dir and create it f not exists
|
963 |
$ftpdirs=explode("/", untrailingslashit($this->job['ftpdir']));
|
964 |
foreach ($ftpdirs as $ftpdir) {
|
965 |
if (empty($ftpdir))
|
966 |
continue;
|
967 |
if (!@ftp_chdir($ftp_conn_id, $ftpdir)) {
|
968 |
-
trigger_error('"'.$ftpdir.'" '.__('FTP
|
969 |
if (@ftp_mkdir($ftp_conn_id, $ftpdir)) {
|
970 |
-
trigger_error('"'.$ftpdir.'" '.__('FTP
|
971 |
ftp_chdir($ftp_conn_id, $ftpdir);
|
972 |
} else {
|
973 |
-
trigger_error('"'.$ftpdir.'" '.__('FTP
|
974 |
}
|
975 |
}
|
976 |
}
|
977 |
-
|
978 |
if (ftp_put($ftp_conn_id, $this->job['ftpdir'].$this->backupfile, $this->backupdir.$this->backupfile, FTP_BINARY)) //transfere file
|
979 |
trigger_error(__('Backup File transferred to FTP Server:','backwpup').' '.$this->job['ftpdir'].$this->backupfile,E_USER_NOTICE);
|
980 |
else
|
981 |
trigger_error(__('Can not transfer backup to FTP server.','backwpup'),E_USER_ERROR);
|
982 |
-
|
983 |
if ($this->job['ftpmaxbackups']>0) { //Delete old backups
|
984 |
$backupfilelist=array();
|
985 |
if ($filelist=ftp_nlist($ftp_conn_id, $this->job['ftpdir'])) {
|
@@ -993,7 +994,7 @@ class backwpup_dojob {
|
|
993 |
for ($i=$this->job['ftpmaxbackups'];$i<sizeof($backupfilelist);$i++) {
|
994 |
if (ftp_delete($ftp_conn_id, $this->job['ftpdir'].$backupfilelist[$i])) //delte files on ftp
|
995 |
$numdeltefiles++;
|
996 |
-
else
|
997 |
trigger_error(__('Can not delete file on FTP Server:','backwpup').' '.$this->job['ftpdir'].$backupfilelist[$i],E_USER_ERROR);
|
998 |
}
|
999 |
if ($numdeltefiles>0)
|
@@ -1001,16 +1002,16 @@ class backwpup_dojob {
|
|
1001 |
}
|
1002 |
}
|
1003 |
}
|
1004 |
-
ftp_close($ftp_conn_id);
|
1005 |
|
1006 |
-
}
|
1007 |
|
1008 |
private function destination_mail() {
|
1009 |
if (empty($this->job['mailaddress']))
|
1010 |
return false;
|
1011 |
-
|
1012 |
-
trigger_error(__('Prepare Sending
|
1013 |
-
|
1014 |
//Crate PHP Mailer
|
1015 |
require_once(ABSPATH.WPINC.'/class-phpmailer.php');
|
1016 |
require_once(ABSPATH.WPINC.'/class-smtp.php');
|
@@ -1038,16 +1039,16 @@ class backwpup_dojob {
|
|
1038 |
$phpmailer->IsMail();
|
1039 |
trigger_error(__('Send mail with PHP mail','backwpup'),E_USER_NOTICE);
|
1040 |
}
|
1041 |
-
|
1042 |
|
1043 |
trigger_error(__('Creating mail','backwpup'),E_USER_NOTICE);
|
1044 |
$phpmailer->From = $this->cfg['mailsndemail'];
|
1045 |
$phpmailer->FromName = $this->cfg['mailsndname'];
|
1046 |
-
$phpmailer->AddAddress($this->job['mailaddress']);
|
1047 |
$phpmailer->Subject = __('BackWPup File from','backwpup').' '.date_i18n('Y-m-d H:i',$this->job['starttime']).': '.$this->job['name'];
|
1048 |
$phpmailer->IsHTML(false);
|
1049 |
$phpmailer->Body = 'Backup File';
|
1050 |
-
|
1051 |
//check file Size
|
1052 |
if (!empty($this->job['mailefilesize'])) {
|
1053 |
$maxfilezise=abs($this->job['mailefilesize']*1024*1024);
|
@@ -1056,23 +1057,23 @@ class backwpup_dojob {
|
|
1056 |
return false;
|
1057 |
}
|
1058 |
}
|
1059 |
-
|
1060 |
trigger_error(__('Adding Attachment to mail','backwpup'),E_USER_NOTICE);
|
1061 |
$this->need_free_memory(filesize($this->backupdir.$this->backupfile)*5);
|
1062 |
-
$phpmailer->AddAttachment($this->backupdir.$this->backupfile);
|
1063 |
-
|
1064 |
trigger_error(__('Send mail....','backwpup'),E_USER_NOTICE);
|
1065 |
if (false == $phpmailer->Send()) {
|
1066 |
trigger_error(__('Can not send mail:','backwpup').' '.$phpmailer->ErrorInfo,E_USER_ERROR);
|
1067 |
} else {
|
1068 |
trigger_error(__('Mail send!!!','backwpup'),E_USER_NOTICE);
|
1069 |
-
}
|
1070 |
-
|
1071 |
}
|
1072 |
|
1073 |
private function destination_s3() {
|
1074 |
-
|
1075 |
-
if (empty($this->job['awsAccessKey']) or empty($this->job['awsSecretKey']) or empty($this->job['awsBucket']))
|
1076 |
return false;
|
1077 |
|
1078 |
if (!(extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll'))) {
|
@@ -1080,9 +1081,9 @@ class backwpup_dojob {
|
|
1080 |
return false;
|
1081 |
}
|
1082 |
|
1083 |
-
if (!class_exists('S3'))
|
1084 |
require_once(plugin_dir_path(__FILE__).'libs/S3.php');
|
1085 |
-
|
1086 |
$s3 = new S3($this->job['awsAccessKey'], $this->job['awsSecretKey'], $this->job['awsSSL']);
|
1087 |
|
1088 |
if (in_array($this->job['awsBucket'],$s3->listBuckets())) {
|
@@ -1092,7 +1093,7 @@ class backwpup_dojob {
|
|
1092 |
trigger_error(__('Backup File transferred to S3://','backwpup').$this->job['awsBucket'].'/'.$this->job['awsdir'].$this->backupfile,E_USER_NOTICE);
|
1093 |
else
|
1094 |
trigger_error(__('Can not transfer backup to S3.','backwpup'),E_USER_ERROR);
|
1095 |
-
|
1096 |
if ($this->job['awsmaxbackups']>0) { //Delete old backups
|
1097 |
$backupfilelist=array();
|
1098 |
if (($contents = $s3->getBucket($this->job['awsBucket'],$this->job['awsdir'])) !== false) {
|
@@ -1110,7 +1111,7 @@ class backwpup_dojob {
|
|
1110 |
for ($i=$this->job['awsmaxbackups'];$i<sizeof($backupfilelist);$i++) {
|
1111 |
if ($s3->deleteObject($this->job['awsBucket'], $this->job['awsdir'].$backupfilelist[$i])) //delte files on S3
|
1112 |
$numdeltefiles++;
|
1113 |
-
else
|
1114 |
trigger_error(__('Can not delete file on S3//:','backwpup').$this->job['awsBucket'].'/'.$this->job['awsdir'].$backupfilelist[$i],E_USER_ERROR);
|
1115 |
}
|
1116 |
if ($numdeltefiles>0)
|
@@ -1128,7 +1129,7 @@ class backwpup_dojob {
|
|
1128 |
//Delete old Backupfiles
|
1129 |
$backupfilelist=array();
|
1130 |
if (!empty($this->job['maxbackups'])) {
|
1131 |
-
if ( $dir = @opendir($this->job['backupdir']) ) { //make file list
|
1132 |
while (($file = readdir($dir)) !== false ) {
|
1133 |
if ('backwpup_'.$this->jobid.'_' == substr($file,0,strlen('backwpup_'.$this->jobid.'_')) and $this->backupfileformat == substr($file,-strlen($this->backupfileformat)))
|
1134 |
$backupfilelist[]=$file;
|
@@ -1147,29 +1148,33 @@ class backwpup_dojob {
|
|
1147 |
}
|
1148 |
}
|
1149 |
}
|
1150 |
-
|
1151 |
public function __destruct() {
|
1152 |
global $backwpup_logfile;
|
1153 |
-
|
1154 |
if (is_file($this->backupdir.$this->backupfile)) {
|
1155 |
-
|
|
|
1156 |
}
|
1157 |
|
|
|
|
|
|
|
1158 |
if (is_file($this->tempdir.DB_NAME.'.sql') ) { //delete sql temp file
|
1159 |
unlink($this->tempdir.DB_NAME.'.sql');
|
1160 |
}
|
1161 |
-
|
1162 |
if (is_file($this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml') ) { //delete WP XML Export temp file
|
1163 |
unlink($this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml');
|
1164 |
}
|
1165 |
-
|
1166 |
if (empty($this->job['backupdir']) and is_file($this->backupdir.$this->backupfile)) { //delete backup file in temp dir
|
1167 |
unlink($this->backupdir.$this->backupfile);
|
1168 |
}
|
1169 |
-
|
1170 |
//delete old logs
|
1171 |
if (!empty($this->cfg['maxlogs'])) {
|
1172 |
-
if ( $dir = @opendir($this->logdir) ) { //make file list
|
1173 |
while (($file = readdir($dir)) !== false ) {
|
1174 |
if ('backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and ".html" == substr($file,-5))
|
1175 |
$logfilelist[]=$file;
|
@@ -1186,8 +1191,8 @@ class backwpup_dojob {
|
|
1186 |
if ($numdeltefiles>0)
|
1187 |
trigger_error($numdeltefiles.' '.__('old Log files deleted!!!','backwpup'),E_USER_NOTICE);
|
1188 |
}
|
1189 |
-
}
|
1190 |
-
|
1191 |
$jobs=get_option('backwpup_jobs');
|
1192 |
$jobs[$this->jobid]['stoptime']=current_time('timestamp');
|
1193 |
$jobs[$this->jobid]['lastrun']=$jobs[$this->jobid]['starttime'];
|
@@ -1197,13 +1202,21 @@ class backwpup_dojob {
|
|
1197 |
|
1198 |
//write runtime header
|
1199 |
$fd=@fopen($backwpup_logfile,"r+");
|
|
|
1200 |
while (!feof($fd)) {
|
1201 |
$line=@fgets($fd);
|
1202 |
if (stripos($line,"<meta name=\"backwpup_jobruntime\"") !== false) {
|
1203 |
@fseek($fd,$filepos);
|
1204 |
@fputs($fd,str_pad("<meta name=\"backwpup_jobruntime\" content=\"".$jobs[$this->jobid]['lastruntime']."\" />",100)."\n");
|
1205 |
-
|
|
|
|
|
|
|
|
|
|
|
1206 |
}
|
|
|
|
|
1207 |
$filepos=ftell($fd);
|
1208 |
}
|
1209 |
@fclose($fd);
|
@@ -1222,7 +1235,7 @@ class backwpup_dojob {
|
|
1222 |
if ($sendmail) {
|
1223 |
$mailbody=__("Jobname:","backwpup")." ".$logdata['name']."\n";
|
1224 |
$mailbody.=__("Jobtype:","backwpup")." ".$logdata['type']."\n";
|
1225 |
-
if (!empty($logdata['errors']))
|
1226 |
$mailbody.=__("Errors:","backwpup")." ".$logdata['errors']."\n";
|
1227 |
if (!empty($logdata['warnings']))
|
1228 |
$mailbody.=__("Warnings:","backwpup")." ".$logdata['warnings']."\n";
|
1 |
<?php
|
2 |
+
// don't load directly
|
3 |
+
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
|
6 |
+
|
7 |
+
//function for PHP error handling
|
8 |
function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
|
9 |
global $backwpup_logfile;
|
10 |
+
|
11 |
//genrate timestamp
|
12 |
if (!function_exists('memory_get_usage')) { // test if memory functions compiled in
|
13 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
14 |
} else {
|
15 |
if (version_compare(phpversion(), '5.2.0', '<'))
|
16 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage())."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage())."|Mem Limit: ".ini_get('memory_limit')."]\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
17 |
+
else
|
18 |
$timestamp="<span style=\"background-color:c3c3c3;\" title=\"[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage(true))."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage(true))."|Mem Limit: ".ini_get('memory_limit')."]\">".date_i18n('Y-m-d H:i.s').":</span> ";
|
19 |
}
|
20 |
+
|
21 |
switch ($errno) {
|
22 |
case E_NOTICE:
|
23 |
case E_USER_NOTICE:
|
36 |
break;
|
37 |
case E_DEPRECATED:
|
38 |
case E_USER_DEPRECATED:
|
39 |
+
$massage=$timestamp."<span>".__('[DEPRECATED]','backwpup')." ".$errstr."</span>";
|
40 |
break;
|
41 |
case E_STRICT:
|
42 |
$massage=$timestamp."<span>".__('[STRICT NOTICE]','backwpup')." ".$errstr."</span>";
|
48 |
$massage=$timestamp."<span>[".$errno."] ".$errstr."</span>";
|
49 |
break;
|
50 |
}
|
51 |
+
|
52 |
if (!empty($massage)) {
|
53 |
//wirte log file
|
54 |
$fd=@fopen($backwpup_logfile,"a+");
|
55 |
@fputs($fd,$massage."<br />\n");
|
56 |
@fclose($fd);
|
57 |
+
|
58 |
+
//output on run now
|
59 |
if (!defined('DOING_CRON')) {
|
60 |
echo $massage."<script type=\"text/javascript\">window.scrollBy(0, 15);</script><br />\n";
|
61 |
@flush();
|
62 |
@ob_flush();
|
63 |
}
|
64 |
+
|
65 |
//write new log header
|
66 |
if (isset($errors) or isset($warnings)) {
|
67 |
$fd=@fopen($backwpup_logfile,"r+");
|
81 |
}
|
82 |
@fclose($fd);
|
83 |
}
|
84 |
+
|
85 |
if ($errno==E_ERROR or $errno==E_CORE_ERROR or $errno==E_COMPILE_ERROR) //Die on fatal php errors.
|
86 |
die();
|
87 |
+
|
88 |
|
89 |
@set_time_limit(300); //300 is most webserver time limit. 0= max time! Give script 5 min. more to work.
|
90 |
//true for no more php error hadling.
|
100 |
$logheader=backwpup_read_logheader($backwpup_logfile); //read waring count from log header
|
101 |
$cfg=get_option('backwpup'); //load config
|
102 |
$jobs=get_option('backwpup_jobs'); //load job options
|
103 |
+
|
104 |
if (!empty($jobs[$logheader['jobid']]['stoptime'])) //abort if job exits normaly
|
105 |
return;
|
106 |
+
|
107 |
+
backwpup_joberrorhandler(E_USER_WARNING, __('Job shutdown function is working! Please delete temp Backup files by hand.','backwpup'), __FILE__, __LINE__);
|
108 |
+
|
109 |
//try to get last error
|
110 |
$lasterror=error_get_last();
|
111 |
backwpup_joberrorhandler($lasterror['type'], __('Last ERROR:','backwpup').' '.$lasterror['message'], $lasterror['file'], $lasterror['line']);
|
112 |
+
|
113 |
//set Temp Dir
|
114 |
$tempdir=trailingslashit($cfg['dirtemp']);
|
115 |
+
if ($tempdir=='/')
|
116 |
$tempdir=backwpup_get_upload_dir();
|
117 |
+
|
118 |
if (is_file($tempdir.DB_NAME.'.sql') ) { //delete sql temp file
|
119 |
unlink($tempdir.DB_NAME.'.sql');
|
120 |
}
|
121 |
+
|
122 |
if (is_file($tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml') ) { //delete WP XML Export temp file
|
123 |
unlink($tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml');
|
124 |
}
|
125 |
+
|
126 |
$jobs[$logheader['jobid']]['stoptime']=current_time('timestamp');
|
127 |
$jobs[$logheader['jobid']]['lastrun']=$jobs[$logheader['jobid']]['starttime'];
|
128 |
$jobs[$logheader['jobid']]['lastruntime']=$jobs[$logheader['jobid']]['stoptime']-$jobs[$logheader['jobid']]['starttime'];
|
155 |
if ($sendmail) {
|
156 |
$mailbody=__("Jobname:","backwpup")." ".$logdata['name']."\n";
|
157 |
$mailbody.=__("Jobtype:","backwpup")." ".$logdata['type']."\n";
|
158 |
+
if (!empty($logdata['errors']))
|
159 |
$mailbody.=__("Errors:","backwpup")." ".$logdata['errors']."\n";
|
160 |
if (!empty($logdata['warnings']))
|
161 |
$mailbody.=__("Warnings:","backwpup")." ".$logdata['warnings']."\n";
|
162 |
wp_mail($jobs[$logheader['jobid']]['mailaddresslog'],__('BackWPup Log File from','backwpup').' '.date_i18n('Y-m-d H:i',$jobs[$logheader['jobid']]['starttime']).': '.$jobs[$logheader['jobid']]['name'] ,$mailbody,'',array($backwpup_logfile));
|
163 |
+
}
|
164 |
}
|
165 |
|
166 |
/**
|
168 |
*
|
169 |
*/
|
170 |
class backwpup_dojob {
|
171 |
+
|
172 |
private $jobid=0;
|
173 |
private $filelist=array();
|
174 |
private $tempfilelist=array();
|
182 |
private $tempdir='';
|
183 |
private $cfg=array();
|
184 |
private $job=array();
|
185 |
+
|
186 |
public function __construct($jobid) {
|
187 |
global $backwpup_logfile,$backwpup_dojob;
|
188 |
@ini_get('safe_mode','Off'); //disable safe mode
|
204 |
$this->backupfileformat=$this->job['fileformart'];
|
205 |
//set Temp Dir
|
206 |
$this->tempdir=trailingslashit($this->cfg['dirtemp']);
|
207 |
+
if (empty($this->tempdir) or $this->tempdir=='/')
|
208 |
$this->tempdir=backwpup_get_upload_dir();
|
209 |
//set Backup Dir
|
210 |
$this->backupdir=$this->job['backupdir'];
|
217 |
$this->logdir=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'backwpup-'.$rand.'-logs/';
|
218 |
}
|
219 |
//set Backup file name only for jos that makes backups
|
220 |
+
if (in_array('FILE',$this->todo) or in_array('DB',$this->todo) or in_array('WPEXP',$this->todo))
|
221 |
$this->backupfile='backwpup_'.$this->jobid.'_'.date_i18n('Y-m-d_H-i-s').$this->backupfileformat;
|
222 |
//set Log file name
|
223 |
+
$this->logfile='backwpup_log_'.date_i18n('Y-m-d_H-i-s').'.html';
|
224 |
$backwpup_logfile=$this->logdir.$this->logfile;
|
225 |
//Create log file
|
226 |
if (!$this->_check_folders($this->logdir))
|
234 |
@fputs($fd,"<meta name=\"backwpup_jobid\" content=\"".$this->jobid."\" />\n");
|
235 |
@fputs($fd,"<meta name=\"backwpup_jobname\" content=\"".$this->job['name']."\" />\n");
|
236 |
@fputs($fd,"<meta name=\"backwpup_jobtype\" content=\"".$this->job['type']."\" />\n");
|
237 |
+
if (!empty($this->backupfile))
|
238 |
+
@fputs($fd,"<meta name=\"backwpup_backupfile\" content=\"".$this->backupfile."\" />\n");
|
239 |
+
@fputs($fd,str_pad("<meta name=\"backwpup_backupfilesize\" content=\"0\" />",100)."\n");
|
240 |
@fputs($fd,str_pad("<meta name=\"backwpup_jobruntime\" content=\"0\" />",100)."\n");
|
241 |
@fputs($fd,"<title>".sprintf(__('BackWPup Log for %1$s from %2$s at %3$s','backwpup'),$this->job['name'],date_i18n(get_option('date_format')),date_i18n(get_option('time_format')))."</title>\n</head>\n<body style=\"font-family:monospace;font-size:12px;white-space:nowrap;\">\n");
|
242 |
@fclose($fd);
|
243 |
//set function for PHP user defineid error handling
|
244 |
if (defined(WP_DEBUG) and WP_DEBUG)
|
245 |
set_error_handler('backwpup_joberrorhandler',E_ALL | E_STRICT);
|
246 |
+
else
|
247 |
set_error_handler('backwpup_joberrorhandler',E_ALL & ~E_NOTICE);
|
248 |
//set a schutdown function.
|
249 |
register_shutdown_function('backwpup_jobshutdown');
|
253 |
return false;
|
254 |
}
|
255 |
//check max script execution tme
|
256 |
+
if (ini_get('safe_mode') or strtolower(ini_get('safe_mode'))=='on' or ini_get('safe_mode')=='1')
|
257 |
trigger_error(sprintf(__('PHP Safe Mode is on!!! Max exec time is %1$d sec.','backwpup'),ini_get('max_execution_time')),E_USER_WARNING);
|
258 |
// check function for memorylimit
|
259 |
if (!function_exists('memory_get_usage')) {
|
260 |
ini_set('memory_limit', apply_filters( 'admin_memory_limit', '256M' )); //Wordpress default
|
261 |
+
trigger_error(sprintf(__('Memory limit set to %1$s ,because can not use PHP: memory_get_usage() function to dynamically increase the Memory!','backwpup'),ini_get('memory_limit')),E_USER_WARNING);
|
262 |
}
|
263 |
//run job parts
|
264 |
foreach($this->todo as $key => $value) {
|
281 |
elseif ($this->backupfileformat==".tar.gz" or $this->backupfileformat==".tar.bz2" or $this->backupfileformat==".tar")
|
282 |
$this->tar_pack_files();
|
283 |
}
|
284 |
+
if (is_file($this->backupdir.$this->backupfile)) { // Put backup file to destination
|
285 |
$this->destination_mail();
|
286 |
$this->destination_ftp();
|
287 |
$this->destination_s3();
|
288 |
$this->destination_dir();
|
289 |
}
|
290 |
+
|
291 |
foreach($this->todo as $key => $value) {
|
292 |
switch ($value) {
|
293 |
case 'CHECK':
|
297 |
$this->optimize_db();
|
298 |
break;
|
299 |
}
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
private function _check_folders($folder) {
|
304 |
if (!is_dir($folder)) { //create dir if not exists
|
305 |
if (!mkdir($folder,0777,true)) {
|
308 |
}
|
309 |
}
|
310 |
if (!is_writeable($folder)) { //test if folder wirteable
|
311 |
+
trigger_error(sprintf(__('Can not write to Folder: %1$s','backwpup'),$folder),E_USER_ERROR);
|
312 |
+
return false;
|
313 |
}
|
314 |
//create .htaccess for apache and index.html for other
|
315 |
if (strtolower(substr($_SERVER["SERVER_SOFTWARE"],0,6))=="apache") { //check if it a apache webserver
|
324 |
if($file = fopen($folder.'index.html', 'w')) {
|
325 |
fwrite($file,"\n");
|
326 |
fclose($file);
|
327 |
+
}
|
328 |
}
|
329 |
if (!is_file($folder.'index.php')) {
|
330 |
if($file = fopen($folder.'index.php', 'w')) {
|
331 |
fwrite($file,"\n");
|
332 |
fclose($file);
|
333 |
+
}
|
334 |
}
|
335 |
}
|
336 |
return true;
|
337 |
}
|
338 |
+
|
339 |
private function need_free_memory($memneed) {
|
340 |
//fail back if fuction not exist
|
341 |
if (!function_exists('memory_get_usage'))
|
345 |
trigger_error(sprintf(__('PHP Safe Mode is on!!! Can not increase Memory Limit is %1$s','backwpup'),ini_get('memory_limit')),E_USER_WARNING);
|
346 |
return false;
|
347 |
}
|
348 |
+
|
349 |
//calc mem to bytes
|
350 |
if (strtoupper(substr(trim(ini_get('memory_limit')),-1))=='K')
|
351 |
$memory=trim(substr(ini_get('memory_limit'),0,-1))*1024;
|
355 |
$memory=trim(substr(ini_get('memory_limit'),0,-1))*1024*1024*1024;
|
356 |
else
|
357 |
$memory=trim(ini_get('memory_limit'));
|
358 |
+
|
359 |
//use real memory at php version 5.2.0
|
360 |
if (version_compare(phpversion(), '5.2.0', '<'))
|
361 |
$memnow=memory_get_usage();
|
362 |
+
else
|
363 |
$memnow=memory_get_usage(true);
|
364 |
+
|
365 |
//need memory
|
366 |
$needmemory=$memnow+$memneed;
|
367 |
+
|
368 |
+
// increase Memory
|
369 |
+
if ($needmemory>$memory) {
|
370 |
$newmemory=round($needmemory/1024/1024)+1;
|
371 |
+
if ($oldmem=ini_set('memory_limit', $newmemory.'M'))
|
372 |
trigger_error(sprintf(__('Memory increased from %1$s to %2$s','backwpup'),$oldmem,ini_get('memory_limit')),E_USER_NOTICE);
|
373 |
+
else
|
374 |
trigger_error(sprintf(__('Can not increase Memory Limit is %1$s','backwpup'),ini_get('memory_limit')),E_USER_WARNING);
|
375 |
}
|
376 |
+
return true;
|
377 |
}
|
378 |
+
|
379 |
private function maintenance_mode($enable = false) {
|
380 |
if (!$this->job['maintenance'])
|
381 |
return;
|
382 |
+
|
383 |
if ( $enable ) {
|
384 |
trigger_error(__('Set Blog to Maintenance Mode','backwpup'),E_USER_NOTICE);
|
385 |
if ( class_exists('WPMaintenanceMode') ) { //Support for WP Maintenance Mode Plugin
|
386 |
+
update_option('wp-maintenance-mode-msqld','1');
|
387 |
} elseif ( class_exists('MaintenanceMode') ) { //Support for Maintenance Mode Plugin
|
388 |
$mamo=get_option('plugin_maintenance-mode');
|
389 |
$mamo['mamo_activate']='on_'.current_time('timestamp');
|
390 |
$mamo['mamo_backtime_days']='0';
|
391 |
$mamo['mamo_backtime_hours']='0';
|
392 |
$mamo['mamo_backtime_mins']='5';
|
393 |
+
update_option('plugin_maintenance-mode',$mamo);
|
394 |
} else { //WP Support
|
395 |
$fdmain=fopen(trailingslashit(ABSPATH).'.maintenance','w');
|
396 |
fputs($fdmain,'<?php $upgrading = ' . time() . '; ?>');
|
397 |
+
fclose($fdmain);
|
398 |
}
|
399 |
} else {
|
400 |
trigger_error(__('Set Blog to normal Mode','backwpup'),E_USER_NOTICE);
|
401 |
if ( class_exists('WPMaintenanceMode') ) { //Support for WP Maintenance Mode Plugin
|
402 |
+
update_option('wp-maintenance-mode-msqld','0');
|
403 |
} elseif ( class_exists('MaintenanceMode') ) { //Support for Maintenance Mode Plugin
|
404 |
$mamo=get_option('plugin_maintenance-mode');
|
405 |
$mamo['mamo_activate']='off';
|
406 |
+
update_option('plugin_maintenance-mode',$mamo);
|
407 |
} else { //WP Support
|
408 |
@unlink(trailingslashit(ABSPATH).'.maintenance');
|
409 |
}
|
410 |
}
|
411 |
}
|
412 |
+
|
413 |
private function check_db() {
|
414 |
global $wpdb;
|
415 |
+
|
416 |
trigger_error(__('Run Database check...','backwpup'),E_USER_NOTICE);
|
417 |
+
|
418 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
419 |
//exclude tables from check
|
420 |
foreach($tables as $tablekey => $tablevalue) {
|
421 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
422 |
unset($tables[$tablekey]);
|
423 |
}
|
424 |
+
|
425 |
//check tables
|
426 |
if (sizeof($tables)>0) {
|
427 |
$this->maintenance_mode(true);
|
432 |
elseif ($check['Msg_type']=='warning')
|
433 |
trigger_error(sprintf(__('Result of table check for %1$s is: %2$s','backwpup'), $table, $check['Msg_text']),E_USER_WARNING);
|
434 |
else
|
435 |
+
trigger_error(sprintf(__('Result of table check for %1$s is: %2$s','backwpup'), $table, $check['Msg_text']),E_USER_NOTICE);
|
436 |
+
|
437 |
if ($sqlerr=mysql_error($wpdb->dbh)) //aditional SQL error
|
438 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
439 |
//Try to Repair tabele
|
444 |
elseif ($repair['Msg_type']=='warning')
|
445 |
trigger_error(sprintf(__('Result of table repair for %1$s is: %2$s','backwpup'), $table, $repair['Msg_text']),E_USER_WARNING);
|
446 |
else
|
447 |
+
trigger_error(sprintf(__('Result of table repair for %1$s is: %2$s','backwpup'), $table, $repair['Msg_text']),E_USER_NOTICE);
|
448 |
+
|
449 |
if ($sqlerr=mysql_error($wpdb->dbh)) //aditional SQL error
|
450 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
451 |
}
|
455 |
trigger_error(__('Database check done!','backwpup'),E_USER_NOTICE);
|
456 |
} else {
|
457 |
trigger_error(__('No Tables to check','backwpup'),E_USER_WARNING);
|
458 |
+
}
|
459 |
}
|
460 |
|
461 |
private function dump_db_table($table,$status,$file) {
|
465 |
fwrite($file, "--\n");
|
466 |
fwrite($file, "-- Table structure for table $table\n");
|
467 |
fwrite($file, "--\n\n");
|
468 |
+
fwrite($file, "DROP TABLE IF EXISTS `" . $table . "`;\n");
|
469 |
fwrite($file, "/*!40101 SET @saved_cs_client = @@character_set_client */;\n");
|
470 |
fwrite($file, "/*!40101 SET character_set_client = '".mysql_client_encoding()."' */;\n");
|
471 |
//Dump the table structure
|
477 |
$tablestruc=mysql_fetch_assoc($result);
|
478 |
fwrite($file, $tablestruc['Create Table'].";\n");
|
479 |
fwrite($file, "/*!40101 SET character_set_client = @saved_cs_client */;\n");
|
480 |
+
|
481 |
//take data of table
|
482 |
$result=mysql_query("SELECT * FROM `".$table."`");
|
483 |
if (!$result) {
|
484 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), mysql_error(), "SELECT * FROM `".$table."`"),E_USER_ERROR);
|
485 |
return false;
|
486 |
}
|
487 |
+
|
488 |
fwrite($file, "--\n");
|
489 |
fwrite($file, "-- Dumping data for table $table\n");
|
490 |
fwrite($file, "--\n\n");
|
492 |
if ($status['Engine']=='MyISAM')
|
493 |
fwrite($file, "/*!40000 ALTER TABLE `".$table."` DISABLE KEYS */;\n");
|
494 |
|
495 |
+
|
496 |
while ($data = mysql_fetch_assoc($result)) {
|
497 |
$keys = array();
|
498 |
$values = array();
|
523 |
global $wpdb;
|
524 |
trigger_error(__('Run Database Dump to file...','backwpup'),E_USER_NOTICE);
|
525 |
$this->maintenance_mode(true);
|
526 |
+
|
527 |
+
//Tables to backup
|
528 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
529 |
+
if ($sqlerr=mysql_error($wpdb->dbh))
|
530 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, "SHOW TABLES FROM `'.DB_NAME.'`"),E_USER_ERROR);
|
531 |
+
|
532 |
foreach($tables as $tablekey => $tablevalue) {
|
533 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
534 |
unset($tables[$tablekey]);
|
535 |
}
|
536 |
sort($tables);
|
537 |
+
|
538 |
|
539 |
if (sizeof($tables)>0) {
|
540 |
$result=$wpdb->get_results("SHOW TABLE STATUS FROM `".DB_NAME."`;", ARRAY_A); //get table status
|
541 |
+
if ($sqlerr=mysql_error($wpdb->dbh))
|
542 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, "SHOW TABLE STATUS FROM `".DB_NAME."`;"),E_USER_ERROR);
|
543 |
foreach($result as $statusdata) {
|
544 |
$status[$statusdata['Name']]=$statusdata;
|
550 |
fwrite($file, "-- Plugin for WordPress by Daniel Huesken\n");
|
551 |
fwrite($file, "-- http://danielhuesken.de/portfolio/backwpup/\n");
|
552 |
fwrite($file, "-- Blog Name: ".get_option('blogname')."\n");
|
553 |
+
if (defined('WP_SITEURL'))
|
554 |
fwrite($file, "-- Blog URL: ".trailingslashit(WP_SITEURL)."\n");
|
555 |
+
else
|
556 |
fwrite($file, "-- Blog URL: ".trailingslashit(get_option('siteurl'))."\n");
|
557 |
fwrite($file, "-- Blog ABSPATH: ".trailingslashit(ABSPATH)."\n");
|
558 |
fwrite($file, "-- Table Prefix: ".$wpdb->prefix."\n");
|
599 |
trigger_error(__('Add Database Dump to Backup:','backwpup').' '.DB_NAME.'.sql '.backwpup_formatBytes(filesize($this->tempdir.DB_NAME.'.sql')),E_USER_NOTICE);
|
600 |
$this->allfilesize+=filesize($this->tempdir.DB_NAME.'.sql');
|
601 |
$this->filelist[]=array(79001=>$this->tempdir.DB_NAME.'.sql',79003=>DB_NAME.'.sql');
|
602 |
+
|
603 |
$this->maintenance_mode(false);
|
604 |
+
}
|
605 |
+
|
606 |
+
|
607 |
|
608 |
private function export_wp() {
|
609 |
trigger_error(__('Run Wordpress Export to XML file...','backwpup'),E_USER_NOTICE);
|
616 |
} else {
|
617 |
trigger_error(__('Can not Export to XML!','backwpup'),E_USER_ERROR);
|
618 |
}
|
619 |
+
}
|
620 |
|
621 |
private function optimize_db() {
|
622 |
global $wpdb;
|
623 |
+
|
624 |
trigger_error(__('Run Database optimize...','backwpup'),E_USER_NOTICE);
|
625 |
+
|
626 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
627 |
//exclude tables from optimize
|
628 |
foreach($tables as $tablekey => $tablevalue) {
|
629 |
if (in_array($tablevalue,$this->job['dbexclude']))
|
630 |
unset($tables[$tablekey]);
|
631 |
}
|
632 |
+
|
633 |
if (sizeof($tables)>0) {
|
634 |
$this->maintenance_mode(true);
|
635 |
foreach ($tables as $table) {
|
639 |
elseif ($optimize['Msg_type']=='warning')
|
640 |
trigger_error(sprintf(__('Result of table optimize for %1$s is: %2$s','backwpup'), $table, $optimize['Msg_text']),E_USER_WARNING);
|
641 |
else
|
642 |
+
trigger_error(sprintf(__('Result of table optimize for %1$s is: %2$s','backwpup'), $table, $optimize['Msg_text']),E_USER_NOTICE);
|
643 |
+
|
644 |
+
if ($sqlerr=mysql_error($wpdb->dbh))
|
645 |
trigger_error(sprintf(__('BackWPup database error %1$s for query %2$s','backwpup'), $sqlerr, $sqlerr->last_query),E_USER_ERROR);
|
646 |
}
|
647 |
$wpdb->flush();
|
649 |
$this->maintenance_mode(false);
|
650 |
} else {
|
651 |
trigger_error(__('No Tables to optimize','backwpup'),E_USER_WARNING);
|
652 |
+
}
|
653 |
}
|
654 |
|
655 |
private function _file_list_folder( $folder = '', $levels = 100, $excludes,$excludedirs=array()) {
|
680 |
}
|
681 |
}
|
682 |
@closedir( $dir );
|
683 |
+
}
|
684 |
}
|
685 |
+
|
686 |
private function file_list() {
|
687 |
|
688 |
//Make filelist
|
689 |
trigger_error(__('Make a list of files to Backup ....','backwpup'),E_USER_NOTICE);
|
690 |
+
|
691 |
$this->tempfilelist=array();
|
692 |
+
|
693 |
$backwpup_exclude=explode(',',trim($this->job['fileexclude']));
|
694 |
//Exclude Temp Files
|
695 |
$backwpup_exclude[]=$this->tempdir.DB_NAME.'.sql';
|
696 |
$backwpup_exclude[]=$this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml';
|
697 |
$backwpup_exclude=array_unique($backwpup_exclude,SORT_STRING);
|
698 |
+
|
699 |
//File list for blog folders
|
700 |
if ($this->job['backuproot'])
|
701 |
+
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',ABSPATH)),100,$backwpup_exclude,array_merge($this->job['backuprootexcludedirs'],backwpup_get_exclude_wp_dirs(ABSPATH)));
|
702 |
if ($this->job['backupcontent'])
|
703 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',WP_CONTENT_DIR)),100,$backwpup_exclude,array_merge($this->job['backupcontentexcludedirs'],backwpup_get_exclude_wp_dirs(WP_CONTENT_DIR)));
|
704 |
if ($this->job['backupplugins'])
|
705 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',WP_PLUGIN_DIR)),100,$backwpup_exclude,array_merge($this->job['backuppluginsexcludedirs'],backwpup_get_exclude_wp_dirs(WP_PLUGIN_DIR)));
|
706 |
+
if ($this->job['backupthemes'])
|
707 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',trailingslashit(WP_CONTENT_DIR).'themes')),100,$backwpup_exclude,array_merge($this->job['backupthemesexcludedirs'],backwpup_get_exclude_wp_dirs(trailingslashit(WP_CONTENT_DIR).'themes')));
|
708 |
if ($this->job['backupuploads'])
|
709 |
$this->_file_list_folder(untrailingslashit(backwpup_get_upload_dir()),100,$backwpup_exclude,array_merge($this->job['backupuploadsexcludedirs'],backwpup_get_exclude_wp_dirs(backwpup_get_upload_dir())));
|
710 |
+
|
711 |
+
//include dirs
|
712 |
$dirinclude=explode(',',$this->job['dirinclude']);
|
713 |
$dirinclude=array_unique($dirinclude,SORT_STRING);
|
714 |
//Crate file list
|
715 |
if (is_array($dirinclude)) {
|
716 |
foreach($dirinclude as $dirincludevalue) {
|
717 |
+
if (is_dir($dirincludevalue))
|
718 |
$this->_file_list_folder(untrailingslashit(str_replace('\\','/',$dirincludevalue)),100,$backwpup_exclude);
|
719 |
}
|
720 |
}
|
725 |
$this->filelist[]=array(79001=>$files,79003=>str_replace(str_replace('\\','/',trailingslashit(ABSPATH)),'',$files));
|
726 |
}
|
727 |
$this->tempfilelist=array();
|
728 |
+
|
729 |
if (!is_array($this->filelist[0])) {
|
730 |
trigger_error(__('No files to Backup','backwpup'),E_USER_ERROR);
|
731 |
} else {
|
732 |
trigger_error(__('Size off all files:','backwpup').' '.backwpup_formatBytes($this->allfilesize),E_USER_NOTICE);
|
733 |
}
|
734 |
+
|
735 |
+
}
|
736 |
|
737 |
private function zip_files() {
|
738 |
+
|
739 |
if (class_exists('ZipArchive')) { //use php zip lib
|
740 |
trigger_error(__('Create Backup Zip file...','backwpup'),E_USER_NOTICE);
|
741 |
$zip = new ZipArchive;
|
742 |
if ($res=$zip->open($this->backupdir.$this->backupfile,ZIPARCHIVE::CREATE) === TRUE) {
|
743 |
+
foreach($this->filelist as $key => $files) {
|
744 |
if (!is_file($files[79001])) //check file exists
|
745 |
continue;
|
746 |
if ($zip->addFile($files[79001], $files[79003])) {
|
754 |
} else {
|
755 |
trigger_error(__('Can not create Backup ZIP file:','backwpup').' '.$res,E_USER_ERROR);
|
756 |
}
|
757 |
+
|
758 |
} else { //use PclZip
|
759 |
define( 'PCLZIP_TEMPORARY_DIR', $this->tempdir );
|
760 |
+
if (!class_exists('PclZip'))
|
761 |
require_once (plugin_dir_path(__FILE__).'libs/pclzip.lib.php');
|
762 |
+
|
763 |
//Create Zip File
|
764 |
if (is_array($this->filelist[0])) {
|
765 |
$this->need_free_memory(10485760); //10MB free memory for zip
|
766 |
trigger_error(__('Create Backup Zip (PclZip) file...','backwpup'),E_USER_NOTICE);
|
767 |
foreach($this->filelist as $key => $files) {
|
768 |
trigger_error(__('Add File to ZIP file:','backwpup').' '.$files[79001].' '.backwpup_formatBytes(filesize($files[79001])),E_USER_NOTICE);
|
769 |
+
}
|
770 |
$zipbackupfile = new PclZip($this->backupdir.$this->backupfile);
|
771 |
if (0==$zipbackupfile -> create($this->filelist,PCLZIP_OPT_ADD_TEMP_FILE_ON)) {
|
772 |
trigger_error(__('Zip file create:','backwpup').' '.$zipbackupfile->errorInfo(true),E_USER_ERROR);
|
773 |
+
} else {
|
774 |
trigger_error(__('Backup Zip file create done!','backwpup'),E_USER_NOTICE);
|
775 |
}
|
776 |
}
|
777 |
}
|
778 |
}
|
779 |
+
|
780 |
private function tar_pack_files() {
|
781 |
+
|
782 |
if ($this->backupfileformat=='.tar.gz') {
|
783 |
$tarbackup=gzopen($this->backupdir.$this->backupfile,'w9');
|
784 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
786 |
} else {
|
787 |
$tarbackup=fopen($this->backupdir.$this->backupfile,'w');
|
788 |
}
|
789 |
+
|
790 |
if (!$tarbackup) {
|
791 |
trigger_error(__('Can not create TAR Backup file','backwpup'),E_USER_ERROR);
|
792 |
return;
|
793 |
} else {
|
794 |
trigger_error(__('Create Backup Archive file...','backwpup'),E_USER_NOTICE);
|
795 |
}
|
796 |
+
|
797 |
$this->need_free_memory(1048576); //1MB free memory for zip
|
798 |
+
|
799 |
foreach($this->filelist as $key => $files) {
|
800 |
trigger_error(__('Add File to Backup Archive:','backwpup').' '.$files[79001].' '.backwpup_formatBytes(filesize($files[79001])),E_USER_NOTICE);
|
801 |
+
|
802 |
//check file exists
|
803 |
if (!is_file($files[79001]))
|
804 |
continue;
|
805 |
+
|
806 |
// Get file information
|
807 |
$file_information = stat($files[79001]);
|
808 |
|
825 |
"", //device minor number 8
|
826 |
substr($files[79003],101), //prefix for file name 155
|
827 |
""); //fill block 512K
|
828 |
+
|
829 |
// Computes the unsigned Checksum of a file's header
|
830 |
$checksum = 0;
|
831 |
for ($i = 0; $i < 512; $i++)
|
832 |
$checksum += ord(substr($header, $i, 1));
|
833 |
$checksum = pack("a8", sprintf("%07o", $checksum));
|
834 |
+
|
835 |
$header = substr_replace($header, $checksum, 148, 8);
|
836 |
+
|
837 |
if ($this->backupfileformat=='.tar.gz') {
|
838 |
gzwrite($tarbackup, $header);
|
839 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
841 |
} else {
|
842 |
fwrite($tarbackup, $header);
|
843 |
}
|
844 |
+
|
845 |
// read/write files in 512K Blocks
|
846 |
$fd=fopen($files[79001],'rb');
|
847 |
while(!feof($fd)) {
|
858 |
}
|
859 |
fclose($fd);
|
860 |
}
|
861 |
+
|
862 |
+
|
863 |
if ($this->backupfileformat=='.tar.gz') {
|
864 |
gzwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
865 |
+
gzclose($tarbackup);
|
866 |
} elseif ($this->backupfileformat=='.tar.bz2') {
|
867 |
bzwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
868 |
bzclose($tarbackup);
|
869 |
} else {
|
870 |
fwrite($tarbackup, pack("a1024", "")); // Add 1024 bytes of NULLs to designate EOF
|
871 |
+
fclose($tarbackup);
|
872 |
}
|
873 |
+
|
874 |
trigger_error(__('Backup Archive file create done!','backwpup'),E_USER_NOTICE);
|
875 |
}
|
876 |
+
|
877 |
+
|
878 |
private function _ftp_raw_helper($ftp_conn_id,$command) { //FTP Comands helper function
|
879 |
$return=ftp_raw($ftp_conn_id,$command);
|
880 |
if (strtoupper(substr(trim($command),0,4))=="PASS") {
|
902 |
}
|
903 |
}
|
904 |
}
|
905 |
+
|
906 |
+
|
907 |
private function destination_ftp() {
|
908 |
+
|
909 |
+
if (empty($this->job['ftphost']) or empty($this->job['ftpuser']) or empty($this->job['ftppass']))
|
910 |
return false;
|
911 |
+
|
912 |
$ftpport=21;
|
913 |
$ftphost=$this->job['ftphost'];
|
914 |
if (false !== strpos($this->job['ftphost'],':')) //look for port
|
916 |
|
917 |
if (function_exists('ftp_ssl_connect')) { //make SSL FTP connection
|
918 |
$ftp_conn_id = ftp_ssl_connect($ftphost,$ftpport,10);
|
919 |
+
if ($ftp_conn_id)
|
920 |
trigger_error(__('Connected by SSL to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_NOTICE);
|
|
|
921 |
}
|
922 |
if (!$ftp_conn_id) { //make normal FTP conection if SSL not work
|
923 |
$ftp_conn_id = ftp_connect($ftphost,$ftpport,10);
|
924 |
+
if ($ftp_conn_id)
|
925 |
trigger_error(__('Connected insecure to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_NOTICE);
|
|
|
926 |
}
|
927 |
+
|
928 |
if (!$ftp_conn_id) {
|
929 |
trigger_error(__('Can not connect to FTP server:','backwpup').' '.$this->job['ftphost'],E_USER_ERROR);
|
930 |
return false;
|
942 |
}
|
943 |
}
|
944 |
}
|
945 |
+
|
946 |
//if (ftp_login($ftp_conn_id, $jobs[$jobid]['ftpuser'], $jobs[$jobid]['ftppass'])) {
|
947 |
+
if (!$loginok)
|
948 |
return false;
|
949 |
+
|
950 |
//SYSTYPE
|
951 |
$this->_ftp_raw_helper($ftp_conn_id,'SYST');
|
952 |
//PASV
|
953 |
trigger_error(__('FTP Client command:','backwpup').' PASV',E_USER_NOTICE);
|
954 |
if (ftp_pasv($ftp_conn_id, true))
|
955 |
trigger_error(__('Server Completion reply: 227 Entering Passive Mode','backwpup'),E_USER_NOTICE);
|
956 |
+
else
|
957 |
trigger_error(__('FTP Server reply:','backwpup').' '.__('Can not Entering Passive Mode','backwpup'),E_USER_WARNING);
|
958 |
//ALLO show no erros in log if do not work
|
959 |
trigger_error(__('FTP Client command:','backwpup').' ALLO',E_USER_NOTICE);
|
960 |
ftp_alloc($ftp_conn_id,filesize($this->backupdir.$this->backupfile),$result);
|
961 |
trigger_error(__('FTP Server reply:','backwpup').' '.$result,E_USER_NOTICE);
|
962 |
+
|
963 |
//test ftp dir and create it f not exists
|
964 |
$ftpdirs=explode("/", untrailingslashit($this->job['ftpdir']));
|
965 |
foreach ($ftpdirs as $ftpdir) {
|
966 |
if (empty($ftpdir))
|
967 |
continue;
|
968 |
if (!@ftp_chdir($ftp_conn_id, $ftpdir)) {
|
969 |
+
trigger_error('"'.$ftpdir.'" '.__('FTP Folder on Server not exists!','backwpup'),E_USER_WARNING);
|
970 |
if (@ftp_mkdir($ftp_conn_id, $ftpdir)) {
|
971 |
+
trigger_error('"'.$ftpdir.'" '.__('FTP Folder created!','backwpup'),E_USER_NOTICE);
|
972 |
ftp_chdir($ftp_conn_id, $ftpdir);
|
973 |
} else {
|
974 |
+
trigger_error('"'.$ftpdir.'" '.__('FTP Folder on Server can not created!','backwpup'),E_USER_ERROR);
|
975 |
}
|
976 |
}
|
977 |
}
|
978 |
+
|
979 |
if (ftp_put($ftp_conn_id, $this->job['ftpdir'].$this->backupfile, $this->backupdir.$this->backupfile, FTP_BINARY)) //transfere file
|
980 |
trigger_error(__('Backup File transferred to FTP Server:','backwpup').' '.$this->job['ftpdir'].$this->backupfile,E_USER_NOTICE);
|
981 |
else
|
982 |
trigger_error(__('Can not transfer backup to FTP server.','backwpup'),E_USER_ERROR);
|
983 |
+
|
984 |
if ($this->job['ftpmaxbackups']>0) { //Delete old backups
|
985 |
$backupfilelist=array();
|
986 |
if ($filelist=ftp_nlist($ftp_conn_id, $this->job['ftpdir'])) {
|
994 |
for ($i=$this->job['ftpmaxbackups'];$i<sizeof($backupfilelist);$i++) {
|
995 |
if (ftp_delete($ftp_conn_id, $this->job['ftpdir'].$backupfilelist[$i])) //delte files on ftp
|
996 |
$numdeltefiles++;
|
997 |
+
else
|
998 |
trigger_error(__('Can not delete file on FTP Server:','backwpup').' '.$this->job['ftpdir'].$backupfilelist[$i],E_USER_ERROR);
|
999 |
}
|
1000 |
if ($numdeltefiles>0)
|
1002 |
}
|
1003 |
}
|
1004 |
}
|
1005 |
+
ftp_close($ftp_conn_id);
|
1006 |
|
1007 |
+
}
|
1008 |
|
1009 |
private function destination_mail() {
|
1010 |
if (empty($this->job['mailaddress']))
|
1011 |
return false;
|
1012 |
+
|
1013 |
+
trigger_error(__('Prepare Sending backup file with mail...','backwpup'),E_USER_NOTICE);
|
1014 |
+
|
1015 |
//Crate PHP Mailer
|
1016 |
require_once(ABSPATH.WPINC.'/class-phpmailer.php');
|
1017 |
require_once(ABSPATH.WPINC.'/class-smtp.php');
|
1039 |
$phpmailer->IsMail();
|
1040 |
trigger_error(__('Send mail with PHP mail','backwpup'),E_USER_NOTICE);
|
1041 |
}
|
1042 |
+
|
1043 |
|
1044 |
trigger_error(__('Creating mail','backwpup'),E_USER_NOTICE);
|
1045 |
$phpmailer->From = $this->cfg['mailsndemail'];
|
1046 |
$phpmailer->FromName = $this->cfg['mailsndname'];
|
1047 |
+
$phpmailer->AddAddress($this->job['mailaddress']);
|
1048 |
$phpmailer->Subject = __('BackWPup File from','backwpup').' '.date_i18n('Y-m-d H:i',$this->job['starttime']).': '.$this->job['name'];
|
1049 |
$phpmailer->IsHTML(false);
|
1050 |
$phpmailer->Body = 'Backup File';
|
1051 |
+
|
1052 |
//check file Size
|
1053 |
if (!empty($this->job['mailefilesize'])) {
|
1054 |
$maxfilezise=abs($this->job['mailefilesize']*1024*1024);
|
1057 |
return false;
|
1058 |
}
|
1059 |
}
|
1060 |
+
|
1061 |
trigger_error(__('Adding Attachment to mail','backwpup'),E_USER_NOTICE);
|
1062 |
$this->need_free_memory(filesize($this->backupdir.$this->backupfile)*5);
|
1063 |
+
$phpmailer->AddAttachment($this->backupdir.$this->backupfile);
|
1064 |
+
|
1065 |
trigger_error(__('Send mail....','backwpup'),E_USER_NOTICE);
|
1066 |
if (false == $phpmailer->Send()) {
|
1067 |
trigger_error(__('Can not send mail:','backwpup').' '.$phpmailer->ErrorInfo,E_USER_ERROR);
|
1068 |
} else {
|
1069 |
trigger_error(__('Mail send!!!','backwpup'),E_USER_NOTICE);
|
1070 |
+
}
|
1071 |
+
|
1072 |
}
|
1073 |
|
1074 |
private function destination_s3() {
|
1075 |
+
|
1076 |
+
if (empty($this->job['awsAccessKey']) or empty($this->job['awsSecretKey']) or empty($this->job['awsBucket']))
|
1077 |
return false;
|
1078 |
|
1079 |
if (!(extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll'))) {
|
1081 |
return false;
|
1082 |
}
|
1083 |
|
1084 |
+
if (!class_exists('S3'))
|
1085 |
require_once(plugin_dir_path(__FILE__).'libs/S3.php');
|
1086 |
+
|
1087 |
$s3 = new S3($this->job['awsAccessKey'], $this->job['awsSecretKey'], $this->job['awsSSL']);
|
1088 |
|
1089 |
if (in_array($this->job['awsBucket'],$s3->listBuckets())) {
|
1093 |
trigger_error(__('Backup File transferred to S3://','backwpup').$this->job['awsBucket'].'/'.$this->job['awsdir'].$this->backupfile,E_USER_NOTICE);
|
1094 |
else
|
1095 |
trigger_error(__('Can not transfer backup to S3.','backwpup'),E_USER_ERROR);
|
1096 |
+
|
1097 |
if ($this->job['awsmaxbackups']>0) { //Delete old backups
|
1098 |
$backupfilelist=array();
|
1099 |
if (($contents = $s3->getBucket($this->job['awsBucket'],$this->job['awsdir'])) !== false) {
|
1111 |
for ($i=$this->job['awsmaxbackups'];$i<sizeof($backupfilelist);$i++) {
|
1112 |
if ($s3->deleteObject($this->job['awsBucket'], $this->job['awsdir'].$backupfilelist[$i])) //delte files on S3
|
1113 |
$numdeltefiles++;
|
1114 |
+
else
|
1115 |
trigger_error(__('Can not delete file on S3//:','backwpup').$this->job['awsBucket'].'/'.$this->job['awsdir'].$backupfilelist[$i],E_USER_ERROR);
|
1116 |
}
|
1117 |
if ($numdeltefiles>0)
|
1129 |
//Delete old Backupfiles
|
1130 |
$backupfilelist=array();
|
1131 |
if (!empty($this->job['maxbackups'])) {
|
1132 |
+
if ( $dir = @opendir($this->job['backupdir']) ) { //make file list
|
1133 |
while (($file = readdir($dir)) !== false ) {
|
1134 |
if ('backwpup_'.$this->jobid.'_' == substr($file,0,strlen('backwpup_'.$this->jobid.'_')) and $this->backupfileformat == substr($file,-strlen($this->backupfileformat)))
|
1135 |
$backupfilelist[]=$file;
|
1148 |
}
|
1149 |
}
|
1150 |
}
|
1151 |
+
|
1152 |
public function __destruct() {
|
1153 |
global $backwpup_logfile;
|
1154 |
+
|
1155 |
if (is_file($this->backupdir.$this->backupfile)) {
|
1156 |
+
$filesize=filesize($this->backupdir.$this->backupfile);
|
1157 |
+
trigger_error(sprintf(__('Backup Archive File size is %1s','backwpup'),backwpup_formatBytes($filesize)),E_USER_NOTICE);
|
1158 |
}
|
1159 |
|
1160 |
+
if (empty($filesize)) //Set the filezie corectly
|
1161 |
+
$filesize=0;
|
1162 |
+
|
1163 |
if (is_file($this->tempdir.DB_NAME.'.sql') ) { //delete sql temp file
|
1164 |
unlink($this->tempdir.DB_NAME.'.sql');
|
1165 |
}
|
1166 |
+
|
1167 |
if (is_file($this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml') ) { //delete WP XML Export temp file
|
1168 |
unlink($this->tempdir.'wordpress.' . date( 'Y-m-d' ) . '.xml');
|
1169 |
}
|
1170 |
+
|
1171 |
if (empty($this->job['backupdir']) and is_file($this->backupdir.$this->backupfile)) { //delete backup file in temp dir
|
1172 |
unlink($this->backupdir.$this->backupfile);
|
1173 |
}
|
1174 |
+
|
1175 |
//delete old logs
|
1176 |
if (!empty($this->cfg['maxlogs'])) {
|
1177 |
+
if ( $dir = @opendir($this->logdir) ) { //make file list
|
1178 |
while (($file = readdir($dir)) !== false ) {
|
1179 |
if ('backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and ".html" == substr($file,-5))
|
1180 |
$logfilelist[]=$file;
|
1191 |
if ($numdeltefiles>0)
|
1192 |
trigger_error($numdeltefiles.' '.__('old Log files deleted!!!','backwpup'),E_USER_NOTICE);
|
1193 |
}
|
1194 |
+
}
|
1195 |
+
|
1196 |
$jobs=get_option('backwpup_jobs');
|
1197 |
$jobs[$this->jobid]['stoptime']=current_time('timestamp');
|
1198 |
$jobs[$this->jobid]['lastrun']=$jobs[$this->jobid]['starttime'];
|
1202 |
|
1203 |
//write runtime header
|
1204 |
$fd=@fopen($backwpup_logfile,"r+");
|
1205 |
+
$found=0;
|
1206 |
while (!feof($fd)) {
|
1207 |
$line=@fgets($fd);
|
1208 |
if (stripos($line,"<meta name=\"backwpup_jobruntime\"") !== false) {
|
1209 |
@fseek($fd,$filepos);
|
1210 |
@fputs($fd,str_pad("<meta name=\"backwpup_jobruntime\" content=\"".$jobs[$this->jobid]['lastruntime']."\" />",100)."\n");
|
1211 |
+
$found++;
|
1212 |
+
}
|
1213 |
+
if (stripos($line,"<meta name=\"backwpup_backupfilesize\"") !== false) {
|
1214 |
+
@fseek($fd,$filepos);
|
1215 |
+
@fputs($fd,str_pad("<meta name=\"backwpup_backupfilesize\" content=\"".$filesize."\" />",100)."\n");
|
1216 |
+
$found++;
|
1217 |
}
|
1218 |
+
if ($found>=2)
|
1219 |
+
break;
|
1220 |
$filepos=ftell($fd);
|
1221 |
}
|
1222 |
@fclose($fd);
|
1235 |
if ($sendmail) {
|
1236 |
$mailbody=__("Jobname:","backwpup")." ".$logdata['name']."\n";
|
1237 |
$mailbody.=__("Jobtype:","backwpup")." ".$logdata['type']."\n";
|
1238 |
+
if (!empty($logdata['errors']))
|
1239 |
$mailbody.=__("Errors:","backwpup")." ".$logdata['errors']."\n";
|
1240 |
if (!empty($logdata['warnings']))
|
1241 |
$mailbody.=__("Warnings:","backwpup")." ".$logdata['warnings']."\n";
|
app/css/options.css
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
.column-id {
|
2 |
-
width:40px;text-align:center;
|
3 |
-
}
|
4 |
-
.column-runtime, .column-last, .column-next , .column-status {
|
5 |
-
width:125px;
|
6 |
-
}
|
7 |
-
.column-type {
|
8 |
-
width:125px;
|
9 |
-
}
|
10 |
-
.column-size {
|
11 |
-
width:75px;
|
12 |
}
|
1 |
+
.column-id {
|
2 |
+
width:40px;text-align:center;
|
3 |
+
}
|
4 |
+
.column-runtime, .column-last, .column-next , .column-status {
|
5 |
+
width:125px;
|
6 |
+
}
|
7 |
+
.column-type {
|
8 |
+
width:125px;
|
9 |
+
}
|
10 |
+
.column-size {
|
11 |
+
width:75px;
|
12 |
}
|
app/functions.php
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
<?PHP
|
2 |
-
// don't load directly
|
3 |
-
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
-
|
6 |
//Thems Option menu entry
|
7 |
function backwpup_menu_entry() {
|
8 |
$hook = add_management_page(__('BackWPup','backwpup'), __('BackWPup','backwpup'), '10', 'BackWPup','backwpup_options_page') ;
|
@@ -10,6 +10,7 @@ if ( !defined('ABSPATH') )
|
|
10 |
add_contextual_help($hook,backwpup_show_help());
|
11 |
switch($_REQUEST['action']) {
|
12 |
case 'logs':
|
|
|
13 |
register_column_headers($hook,array('cb'=>'<input type="checkbox" />','id'=>__('Job','backwpup'),'type'=>__('Type','backwpup'),'log'=>__('Backup/Log Date/Time','backwpup'),'status'=>__('Status','backwpup'),'size'=>__('Size','backwpup'),'runtime'=>__('Runtime','backwpup')));
|
14 |
break;
|
15 |
case 'edit':
|
@@ -18,18 +19,24 @@ if ( !defined('ABSPATH') )
|
|
18 |
break;
|
19 |
case 'tools':
|
20 |
break;
|
|
|
|
|
|
|
|
|
21 |
case 'runnow':
|
22 |
add_action('load-'.$hook, 'backwpup_send_no_cache_header');
|
23 |
add_action('admin_head-'.$hook, 'backwpup_meta_no_cache');
|
24 |
break;
|
25 |
case 'view_log':
|
26 |
break;
|
|
|
|
|
27 |
default:
|
28 |
register_column_headers($hook,array('cb'=>'<input type="checkbox" />','id'=>__('ID','backwpup'),'jobname'=>__('Job Name','backwpup'),'type'=>__('Type','backwpup'),'next'=>__('Next Run','backwpup'),'last'=>__('Last Run','backwpup')));
|
29 |
break;
|
30 |
}
|
31 |
-
}
|
32 |
-
|
33 |
// Help too display
|
34 |
function backwpup_show_help() {
|
35 |
$help .= '<div class="metabox-prefs">';
|
@@ -42,20 +49,20 @@ if ( !defined('ABSPATH') )
|
|
42 |
var flattr_btn = 'compact';
|
43 |
var flattr_url = 'http://danielhuesken.de/portfolio/backwpup/';
|
44 |
</script><script src=\"http://api.flattr.com/button/load.js\" type=\"text/javascript\"></script>";
|
45 |
-
$help .= "</div>\n";
|
46 |
$help .= '<div class="metabox-prefs">';
|
47 |
$help .= __('Version:', 'backwpup').' '.BACKWPUP_VERSION.' | ';
|
48 |
$help .= __('Author:', 'backwpup').' <a href="http://danielhuesken.de" target="_blank">Daniel Hüsken</a>';
|
49 |
$help .= "</div>\n";
|
50 |
return $help;
|
51 |
}
|
52 |
-
|
53 |
//Options Page
|
54 |
function backwpup_options_page() {
|
55 |
global $wpdb,$backwpup_message,$page_hook;
|
56 |
-
if (!current_user_can(10))
|
57 |
wp_die('No rights');
|
58 |
-
if(!empty($backwpup_message))
|
59 |
echo '<div id="message" class="updated fade"><p><strong>'.$backwpup_message.'</strong></p></div>';
|
60 |
switch($_REQUEST['action']) {
|
61 |
case 'edit':
|
@@ -75,6 +82,9 @@ if ( !defined('ABSPATH') )
|
|
75 |
case 'tools':
|
76 |
require_once(plugin_dir_path(__FILE__).'options-tools.php');
|
77 |
break;
|
|
|
|
|
|
|
78 |
case 'runnow':
|
79 |
$jobid = (int) $_GET['jobid'];
|
80 |
check_admin_referer('runnow-job_' . $jobid);
|
@@ -89,13 +99,13 @@ if ( !defined('ABSPATH') )
|
|
89 |
$jobs=get_option('backwpup_jobs');
|
90 |
require_once(plugin_dir_path(__FILE__).'options.php');
|
91 |
break;
|
92 |
-
}
|
93 |
}
|
94 |
-
|
95 |
//Options Page
|
96 |
function backwpup_options_load() {
|
97 |
global $wpdb,$backwpup_message;
|
98 |
-
if (!current_user_can(10))
|
99 |
wp_die('No rights');
|
100 |
//Css for Admin Section
|
101 |
wp_enqueue_style('BackWpup',plugins_url('css/options.css',__FILE__),'',BACKWPUP_VERSION,'screen');
|
@@ -103,7 +113,7 @@ if ( !defined('ABSPATH') )
|
|
103 |
//For save Options
|
104 |
require_once(plugin_dir_path(__FILE__).'options-save.php');
|
105 |
}
|
106 |
-
|
107 |
//delete Otions
|
108 |
function backwpup_plugin_uninstall() {
|
109 |
delete_option('backwpup');
|
@@ -124,39 +134,39 @@ if ( !defined('ABSPATH') )
|
|
124 |
$jobsettings['type']=implode('+',$todo);
|
125 |
if (empty($jobsettings['type']))
|
126 |
$jobsettings['type']='DB+FILE';
|
127 |
-
|
128 |
if (empty($jobsettings['name']) or !is_string($jobsettings['name']))
|
129 |
$jobsettings['name']= __('New');
|
130 |
-
|
131 |
-
if (!isset($jobsettings['activated']) or !is_bool($jobsettings['activated']))
|
132 |
$jobsettings['activated']=false;
|
133 |
-
|
134 |
if (!isset($jobsettings['scheduletime']) or !is_numeric($jobsettings['scheduletime']))
|
135 |
$jobsettings['scheduletime']=current_time('timestamp');
|
136 |
-
|
137 |
-
if (!isset($jobsettings['scheduleintervaltype']) or !is_int($jobsettings['scheduleintervaltype']))
|
138 |
$jobsettings['scheduleintervaltype']=3600;
|
139 |
if ($jobsettings['scheduleintervaltype']!=60 and $jobsettings['scheduleintervaltype']!=3600 and $jobsettings['scheduleintervaltype']!=86400)
|
140 |
$jobsettings['scheduleintervaltype']=3600;
|
141 |
-
|
142 |
if (!isset($jobsettings['scheduleintervalteimes']) or !is_int($jobsettings['scheduleintervalteimes']) or ($jobsettings['scheduleintervalteimes']<1 and $jobsettings['scheduleintervalteimes']>100))
|
143 |
$jobsettings['scheduleintervalteimes']=1;
|
144 |
-
|
145 |
$jobsettings['scheduleinterval']=$jobsettings['scheduleintervaltype']*$jobsettings['scheduleintervalteimes'];
|
146 |
-
|
147 |
if (!is_string($jobsettings['mailaddresslog']) or false === $pos=strpos($jobsettings['mailaddresslog'],'@') or false === strpos($jobsettings['mailaddresslog'],'.',$pos))
|
148 |
$jobsettings['mailaddresslog']=get_option('admin_email');
|
149 |
-
|
150 |
if (!isset($jobsettings['mailerroronly']) or !is_bool($jobsettings['mailerroronly']))
|
151 |
$jobsettings['mailerroronly']=true;
|
152 |
-
|
153 |
if (!isset($jobsettings['dbexclude']) or !is_array($jobsettings['dbexclude'])) {
|
154 |
$jobsettings['dbexclude']=array();
|
155 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
156 |
foreach ($tables as $table) {
|
157 |
if (substr($table,0,strlen($wpdb->prefix))!=$wpdb->prefix)
|
158 |
$jobsettings['dbexclude'][]=$table;
|
159 |
-
}
|
160 |
}
|
161 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
162 |
foreach($jobsettings['dbexclude'] as $key => $value) {
|
@@ -164,13 +174,13 @@ if ( !defined('ABSPATH') )
|
|
164 |
unset($jobsettings['dbexclude'][$key]);
|
165 |
}
|
166 |
sort($jobsettings['dbexclude']);
|
167 |
-
|
168 |
if (!isset($jobsettings['dbshortinsert']) or !is_bool($jobsettings['dbshortinsert']))
|
169 |
$jobsettings['dbshortinsert']=false;
|
170 |
-
|
171 |
if (!isset($jobsettings['maintenance']) or !is_bool($jobsettings['maintenance']))
|
172 |
$jobsettings['maintenance']=false;
|
173 |
-
|
174 |
if (!isset($jobsettings['fileexclude']) or !is_string($jobsettings['fileexclude']))
|
175 |
$jobsettings['fileexclude']='';
|
176 |
$fileexclude=explode(',',$jobsettings['fileexclude']);
|
@@ -180,8 +190,8 @@ if ( !defined('ABSPATH') )
|
|
180 |
unset($fileexclude[$key]);
|
181 |
}
|
182 |
sort($fileexclude);
|
183 |
-
$jobsettings['fileexclude']=implode(',',$fileexclude);
|
184 |
-
|
185 |
if (!isset($jobsettings['dirinclude']) or !is_string($jobsettings['dirinclude']))
|
186 |
$jobsettings['dirinclude']='';
|
187 |
$dirinclude=explode(',',$jobsettings['dirinclude']);
|
@@ -191,17 +201,17 @@ if ( !defined('ABSPATH') )
|
|
191 |
unset($dirinclude[$key]);
|
192 |
}
|
193 |
sort($dirinclude);
|
194 |
-
$jobsettings['dirinclude']=implode(',',$dirinclude);
|
195 |
|
196 |
if (!isset($jobsettings['backuproot']) or !is_bool($jobsettings['backuproot']))
|
197 |
$jobsettings['backuproot']=true;
|
198 |
-
|
199 |
if (!isset($jobsettings['backupcontent']) or !is_bool($jobsettings['backupcontent']))
|
200 |
$jobsettings['backupcontent']=true;
|
201 |
-
|
202 |
if (!isset($jobsettings['backupplugins']) or !is_bool($jobsettings['backupplugins']))
|
203 |
$jobsettings['backupplugins']=true;
|
204 |
-
|
205 |
if (!isset($jobsettings['backupthemes']) or !is_bool($jobsettings['backupthemes']))
|
206 |
$jobsettings['backupthemes']=true;
|
207 |
|
@@ -252,78 +262,78 @@ if ( !defined('ABSPATH') )
|
|
252 |
unset($jobsettings['backupuploadsexcludedirs'][$key]);
|
253 |
}
|
254 |
sort($jobsettings['backupuploadsexcludedirs']);
|
255 |
-
|
256 |
$fileformarts=array('.zip','.tar.gz','tar.bz2','.tar');
|
257 |
if (!isset($jobsettings['fileformart']) or !in_array($jobsettings['fileformart'],$fileformarts))
|
258 |
$jobsettings['fileformart']='.zip';
|
259 |
-
|
260 |
if (!isset($jobsettings['mailefilesize']) or !is_float($jobsettings['mailefilesize']))
|
261 |
$jobsettings['mailefilesize']=0;
|
262 |
-
|
263 |
if (!isset($jobsettings['backupdir']) or (!is_dir($jobsettings['backupdir']) and !empty($jobsettings['backupdir']))) {
|
264 |
$rand = substr( md5( md5( SECURE_AUTH_KEY ) ), -5 );
|
265 |
-
$jobsettings['backupdir']=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'backwpup-'.$rand.'/';
|
266 |
}
|
267 |
$jobsettings['backupdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['backupdir']))));
|
268 |
if ($jobsettings['backupdir']=='/')
|
269 |
$jobsettings['backupdir']='';
|
270 |
-
|
271 |
if (!isset($jobsettings['maxbackups']) or !is_int($jobsettings['maxbackups']))
|
272 |
$jobsettings['maxbackups']=0;
|
273 |
-
|
274 |
if (!isset($jobsettings['ftphost']) or !is_string($jobsettings['ftphost']))
|
275 |
$jobsettings['ftphost']='';
|
276 |
-
|
277 |
-
if (!isset($jobsettings['ftpuser']) or !is_string($jobsettings['ftpuser']))
|
278 |
$jobsettings['ftpuser']='';
|
279 |
-
|
280 |
if (!isset($jobsettings['ftppass']) or !is_string($jobsettings['ftppass']))
|
281 |
$jobsettings['ftppass']='';
|
282 |
|
283 |
-
if (!isset($jobsettings['ftpdir']) or !is_string($jobsettings['ftpdir']) or $jobsettings['ftpdir']=='/')
|
284 |
$jobsettings['ftpdir']='';
|
285 |
$jobsettings['ftpdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['ftpdir']))));
|
286 |
-
if (substr($jobsettings['ftpdir'],0,1)
|
287 |
-
$jobsettings['ftpdir']=
|
288 |
-
|
289 |
if (!isset($jobsettings['ftpmaxbackups']) or !is_int($jobsettings['ftpmaxbackups']))
|
290 |
$jobsettings['ftpmaxbackups']=0;
|
291 |
-
|
292 |
if (!isset($jobsettings['awsAccessKey']) or !is_string($jobsettings['awsAccessKey']))
|
293 |
$jobsettings['awsAccessKey']='';
|
294 |
-
|
295 |
if (!isset($jobsettings['awsSecretKey']) or !is_string($jobsettings['awsSecretKey']))
|
296 |
$jobsettings['awsSecretKey']='';
|
297 |
-
|
298 |
if (!isset($jobsettings['awsSSL']) or !is_bool($jobsettings['awsSSL']))
|
299 |
$jobsettings['awsSSL']=true;
|
300 |
-
|
301 |
if (!isset($jobsettings['awsBucket']) or !is_string($jobsettings['awsBucket']))
|
302 |
$jobsettings['awsBucket']='';
|
303 |
-
|
304 |
-
if (!isset($jobsettings['awsdir']) or !is_string($jobsettings['awsdir']) or $jobsettings['awsdir']=='/')
|
305 |
$jobsettings['awsdir']='';
|
306 |
$jobsettings['awsdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['awsdir']))));
|
307 |
if (substr($jobsettings['awsdir'],0,1)=='/')
|
308 |
$jobsettings['awsdir']=substr($jobsettings['awsdir'],1);
|
309 |
-
|
310 |
if (!isset($jobsettings['awsmaxbackups']) or !is_int($jobsettings['awsmaxbackups']))
|
311 |
-
$jobsettings['awsmaxbackups']=0;
|
312 |
-
|
313 |
if (!is_string($jobsettings['mailaddress']) or false === $pos=strpos($jobsettings['mailaddress'],'@') or false === strpos($jobsettings['mailaddress'],'.',$pos))
|
314 |
$jobsettings['mailaddress']='';
|
315 |
|
316 |
return $jobsettings;
|
317 |
}
|
318 |
|
319 |
-
|
320 |
//On Plugin activate
|
321 |
function backwpup_plugin_activate() {
|
322 |
//add cron jobs
|
323 |
$jobs=get_option('backwpup_jobs');
|
324 |
-
if (is_array($jobs)) {
|
325 |
foreach ($jobs as $jobid => $jobvalue) {
|
326 |
-
if ($jobvalue['activated'] and wp_get_schedule('backwpup_cron',array('jobid'=>$jobid)) === false)
|
327 |
wp_schedule_event($jobvalue['scheduletime'], 'backwpup_int_'.$jobid, 'backwpup_cron',array('jobid'=>$jobid));
|
328 |
}
|
329 |
}
|
@@ -340,25 +350,25 @@ if ( !defined('ABSPATH') )
|
|
340 |
}
|
341 |
if (empty($cfg['dirlogs'])) {
|
342 |
$rand = substr( md5( md5( SECURE_AUTH_KEY ) ), -5 );
|
343 |
-
$cfg['dirlogs']=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'
|
344 |
}
|
345 |
update_option('backwpup',$cfg);
|
346 |
}
|
347 |
-
|
348 |
//on Plugin deaktivate
|
349 |
function backwpup_plugin_deactivate() {
|
350 |
//remove cron jobs
|
351 |
$jobs=get_option('backwpup_jobs');
|
352 |
wp_clear_scheduled_hook('backwpup_cron');
|
353 |
}
|
354 |
-
|
355 |
//add edit setting to plugins page
|
356 |
function backwpup_plugin_options_link($links) {
|
357 |
$settings_link='<a href="admin.php?page=BackWPup" title="' . __('Go to Settings Page','backwpup') . '" class="edit">' . __('Settings') . '</a>';
|
358 |
-
array_unshift( $links, $settings_link );
|
359 |
return $links;
|
360 |
}
|
361 |
-
|
362 |
//add links on plugins page
|
363 |
function backwpup_plugin_links($links, $file) {
|
364 |
if ($file == BACKWPUP_PLUGIN_BASEDIR.'/backwpup.php') {
|
@@ -368,7 +378,7 @@ if ( !defined('ABSPATH') )
|
|
368 |
}
|
369 |
return $links;
|
370 |
}
|
371 |
-
|
372 |
//Add cron interval
|
373 |
function backwpup_intervals($schedules) {
|
374 |
$jobs=get_option('backwpup_jobs'); //Load Settings
|
@@ -377,9 +387,9 @@ if ( !defined('ABSPATH') )
|
|
377 |
if (!empty($jobvalue['scheduleinterval']))
|
378 |
$intervals['backwpup_int_'.$jobkey]=array('interval' => $jobvalue['scheduleinterval'], 'display' => __('BackWPup Job '.$jobkey, 'backwpup'));
|
379 |
}
|
380 |
-
if (is_array($intervals))
|
381 |
$schedules=array_merge($intervals,$schedules);
|
382 |
-
}
|
383 |
return $schedules;
|
384 |
}
|
385 |
|
@@ -390,14 +400,14 @@ if ( !defined('ABSPATH') )
|
|
390 |
extract($args, EXTR_SKIP );
|
391 |
else
|
392 |
$jobid=$args;
|
393 |
-
if (empty($jobid))
|
394 |
return false;
|
395 |
require_once('backwpup_dojob.php');
|
396 |
$backwpup_dojob= new backwpup_dojob($jobid);
|
397 |
unset($backwpup_dojob);
|
398 |
return $backwpup_logfile;
|
399 |
}
|
400 |
-
|
401 |
//file size
|
402 |
function backwpup_formatBytes($bytes, $precision = 2) {
|
403 |
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
@@ -406,8 +416,8 @@ if ( !defined('ABSPATH') )
|
|
406 |
$pow = min($pow, count($units) - 1);
|
407 |
$bytes /= pow(1024, $pow);
|
408 |
return round($bytes, $precision) . ' ' . $units[$pow];
|
409 |
-
}
|
410 |
-
|
411 |
//echo long backup type name
|
412 |
function backwpup_backup_types($type='',$echo=false) {
|
413 |
$typename='';
|
@@ -420,7 +430,7 @@ if ( !defined('ABSPATH') )
|
|
420 |
break;
|
421 |
case 'DB':
|
422 |
$typename.=__('Database Backup','backwpup')."<br />";
|
423 |
-
break;
|
424 |
case 'FILE':
|
425 |
$typename.=__('File Backup','backwpup')."<br />";
|
426 |
break;
|
@@ -435,16 +445,16 @@ if ( !defined('ABSPATH') )
|
|
435 |
} else {
|
436 |
$typename=array('WPEXP','DB','FILE','OPTIMIZE','CHECK');
|
437 |
}
|
438 |
-
|
439 |
-
if ($echo)
|
440 |
echo $typename;
|
441 |
else
|
442 |
return $typename;
|
443 |
}
|
444 |
-
|
445 |
//read log file header
|
446 |
function backwpup_read_logheader($logfile) {
|
447 |
-
$headers=array("backwpup_version" => "version","backwpup_logtime" => "logtime","backwpup_errors" => "errors","backwpup_warnings" => "warnings","backwpup_jobid" => "jobid","backwpup_jobname" => "name","backwpup_jobtype" => "type","backwpup_jobruntime" => "runtime","backwpup_backupfile" => "backupfile");
|
448 |
if (!is_readable($logfile))
|
449 |
return false;
|
450 |
//Read file
|
@@ -460,14 +470,14 @@ if ( !defined('ABSPATH') )
|
|
460 |
else
|
461 |
$joddata[$field]='';
|
462 |
}
|
463 |
-
|
464 |
if (empty($joddata['logtime']))
|
465 |
$joddata['logtime']=filectime($logfile);
|
466 |
-
|
467 |
return $joddata;
|
468 |
}
|
469 |
-
|
470 |
-
|
471 |
//Dashboard widget
|
472 |
function backwpup_dashboard_output() {
|
473 |
global $wpdb;
|
@@ -483,25 +493,25 @@ if ( !defined('ABSPATH') )
|
|
483 |
closedir( $dir );
|
484 |
rsort($logfiles);
|
485 |
}
|
486 |
-
|
487 |
if (is_array($logfiles)) {
|
488 |
$count=0;
|
489 |
foreach ($logfiles as $logfile) {
|
490 |
$logdata=backwpup_read_logheader($cfg['dirlogs'].'/'.$logfile);
|
491 |
echo '<a href="'.wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile).'" title="'.__('View Log','backwpup').'">'.date_i18n(get_option('date_format'),$logdata['logtime']).' '.date_i18n(get_option('time_format'),$logdata['logtime']).': <i>';
|
492 |
-
if (empty($logdata['name']))
|
493 |
echo $logdata['type'];
|
494 |
else
|
495 |
echo $logdata['name'];
|
496 |
echo '</i>';
|
497 |
-
if($logdata['errors']>0 or $logdata['warnings']>0) {
|
498 |
if ($logdata['errors']>0)
|
499 |
-
echo ' <span style="color:red;">'.$logdata['errors'].' '.__('ERROR(S)','backwpup').'</span>';
|
500 |
if ($logdata['warnings']>0)
|
501 |
-
echo ' <span style="color:yellow;">'.$logdata['warnings'].' '.__('WARNING(S)','backwpup').'</span>';
|
502 |
-
} else {
|
503 |
-
echo ' <span style="color:green;">'.__('OK','backwpup').'</span>';
|
504 |
-
}
|
505 |
echo '</a><br />';
|
506 |
$count++;
|
507 |
if ($count>=5)
|
@@ -512,7 +522,7 @@ if ( !defined('ABSPATH') )
|
|
512 |
}
|
513 |
$jobs=get_option('backwpup_jobs');
|
514 |
echo '<strong>'.__('Scheduled Jobs:','backwpup').'</strong><br />';
|
515 |
-
if (is_array($jobs)) {
|
516 |
foreach ($jobs as $jobid => $jobvalue) {
|
517 |
if (wp_next_scheduled('backwpup_cron',array('jobid'=>$jobid))) {
|
518 |
echo '<a href="'.wp_nonce_url('admin.php?page=BackWPup&action=edit&jobid='.$jobid, 'edit-job').'" title="'.__('Edit Job','backwpup').'">';
|
@@ -529,19 +539,19 @@ if ( !defined('ABSPATH') )
|
|
529 |
echo '<i>'.__('none','backwpup').'</i><br />';
|
530 |
}
|
531 |
}
|
532 |
-
|
533 |
//add dashboard widget
|
534 |
function backwpup_add_dashboard() {
|
535 |
-
wp_add_dashboard_widget( 'backwpup_dashboard_widget', 'BackWPup', 'backwpup_dashboard_output' );
|
536 |
}
|
537 |
-
|
538 |
//turn cache off
|
539 |
function backwpup_meta_no_cache() {
|
540 |
echo "<meta http-equiv=\"expires\" content=\"0\" />\n";
|
541 |
echo "<meta http-equiv=\"pragma\" content=\"no-cache\" />\n";
|
542 |
echo "<meta http-equiv=\"cache-control\" content=\"no-cache\" />\n";
|
543 |
}
|
544 |
-
|
545 |
function backwpup_send_no_cache_header() {
|
546 |
header("Expires: 0");
|
547 |
header("Cache-Control: no-cache, must-revalidate");
|
@@ -564,7 +574,7 @@ if ( !defined('ABSPATH') )
|
|
564 |
// $dir is absolute, $upload_path is (maybe) relative to ABSPATH
|
565 |
$dir = path_join( ABSPATH, $dir );
|
566 |
}
|
567 |
-
}
|
568 |
if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
|
569 |
$dir = ABSPATH . UPLOADS;
|
570 |
}
|
@@ -574,10 +584,10 @@ if ( !defined('ABSPATH') )
|
|
574 |
$dir = untrailingslashit(BLOGUPLOADDIR);
|
575 |
}
|
576 |
}
|
577 |
-
|
578 |
return str_replace('\\','/',trailingslashit($dir));
|
579 |
}
|
580 |
-
|
581 |
function backwpup_get_exclude_wp_dirs($folder) {
|
582 |
$folder=trailingslashit(str_replace('\\','/',$folder));
|
583 |
$excludedir=array();
|
@@ -593,13 +603,127 @@ if ( !defined('ABSPATH') )
|
|
593 |
$excludedir[]=backwpup_get_upload_dir();
|
594 |
//Exclude Backup dirs
|
595 |
$jobs=get_option('backwpup_jobs');
|
596 |
-
foreach($jobs as $jobsvale) {
|
597 |
if (!empty($jobsvale['backupdir']) and $jobsvale['backupdir']!='/')
|
598 |
$excludedir[]=trailingslashit(str_replace('\\','/',$jobsvale['backupdir']));
|
599 |
}
|
600 |
return $excludedir;
|
601 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
602 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
//ajax/normal get buckests select box
|
604 |
function backwpup_get_aws_buckets($args='') {
|
605 |
if (is_array($args)) {
|
@@ -619,13 +743,13 @@ if ( !defined('ABSPATH') )
|
|
619 |
if (empty($awsSecretKey)) {
|
620 |
echo '<span id="awsBucket" style="color:red;">'.__('Missing Secret Access Key!','backwpup').'</span>';
|
621 |
die();
|
622 |
-
}
|
623 |
$s3 = new S3($awsAccessKey, $awsSecretKey, false);
|
624 |
$buckets=@$s3->listBuckets();
|
625 |
if (!is_array($buckets)) {
|
626 |
echo '<span id="awsBucket" style="color:red;">'.__('No Buckets found! Or wrong Keys!','backwpup').'</span>';
|
627 |
die();
|
628 |
-
}
|
629 |
echo '<select name="awsBucket" id="awsBucket">';
|
630 |
foreach ($buckets as $bucket) {
|
631 |
echo "<option ".selected(strtolower($selected),strtolower($bucket),false).">".$bucket."</option>";
|
@@ -634,7 +758,7 @@ if ( !defined('ABSPATH') )
|
|
634 |
if ($ajax)
|
635 |
die();
|
636 |
}
|
637 |
-
|
638 |
// add all action and so on only if plugin loaded.
|
639 |
function backwpup_init() {
|
640 |
//Disabele WP_Corn
|
@@ -644,19 +768,19 @@ if ( !defined('ABSPATH') )
|
|
644 |
//add Menu
|
645 |
add_action('admin_menu', 'backwpup_menu_entry');
|
646 |
//Additional links on the plugin page
|
647 |
-
if (current_user_can(10))
|
648 |
add_filter('plugin_action_links_'.BACKWPUP_PLUGIN_BASEDIR.'/backwpup.php', 'backwpup_plugin_options_link');
|
649 |
-
if (current_user_can('install_plugins'))
|
650 |
add_filter('plugin_row_meta', 'backwpup_plugin_links',10,2);
|
651 |
//add cron intervals
|
652 |
add_filter('cron_schedules', 'backwpup_intervals');
|
653 |
//Actions for Cron job
|
654 |
add_action('backwpup_cron', 'backwpup_dojob');
|
655 |
//add Dashboard widget
|
656 |
-
if (current_user_can(10))
|
657 |
add_action('wp_dashboard_setup', 'backwpup_add_dashboard');
|
658 |
// add ajax function
|
659 |
add_action('wp_ajax_backwpup_get_aws_buckets', 'backwpup_get_aws_buckets');
|
660 |
-
}
|
661 |
|
662 |
?>
|
1 |
<?PHP
|
2 |
+
// don't load directly
|
3 |
+
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
+
|
6 |
//Thems Option menu entry
|
7 |
function backwpup_menu_entry() {
|
8 |
$hook = add_management_page(__('BackWPup','backwpup'), __('BackWPup','backwpup'), '10', 'BackWPup','backwpup_options_page') ;
|
10 |
add_contextual_help($hook,backwpup_show_help());
|
11 |
switch($_REQUEST['action']) {
|
12 |
case 'logs':
|
13 |
+
case 'delete-logs':
|
14 |
register_column_headers($hook,array('cb'=>'<input type="checkbox" />','id'=>__('Job','backwpup'),'type'=>__('Type','backwpup'),'log'=>__('Backup/Log Date/Time','backwpup'),'status'=>__('Status','backwpup'),'size'=>__('Size','backwpup'),'runtime'=>__('Runtime','backwpup')));
|
15 |
break;
|
16 |
case 'edit':
|
19 |
break;
|
20 |
case 'tools':
|
21 |
break;
|
22 |
+
case 'backups':
|
23 |
+
case 'delete-backup':
|
24 |
+
register_column_headers($hook,array('cb'=>'<input type="checkbox" />','id'=>__('Job','backwpup'),'backup'=>__('Backupfile','backwpup'),'size'=>__('Size','backwpup')));
|
25 |
+
break;
|
26 |
case 'runnow':
|
27 |
add_action('load-'.$hook, 'backwpup_send_no_cache_header');
|
28 |
add_action('admin_head-'.$hook, 'backwpup_meta_no_cache');
|
29 |
break;
|
30 |
case 'view_log':
|
31 |
break;
|
32 |
+
case 'delete':
|
33 |
+
case 'copy':
|
34 |
default:
|
35 |
register_column_headers($hook,array('cb'=>'<input type="checkbox" />','id'=>__('ID','backwpup'),'jobname'=>__('Job Name','backwpup'),'type'=>__('Type','backwpup'),'next'=>__('Next Run','backwpup'),'last'=>__('Last Run','backwpup')));
|
36 |
break;
|
37 |
}
|
38 |
+
}
|
39 |
+
|
40 |
// Help too display
|
41 |
function backwpup_show_help() {
|
42 |
$help .= '<div class="metabox-prefs">';
|
49 |
var flattr_btn = 'compact';
|
50 |
var flattr_url = 'http://danielhuesken.de/portfolio/backwpup/';
|
51 |
</script><script src=\"http://api.flattr.com/button/load.js\" type=\"text/javascript\"></script>";
|
52 |
+
$help .= "</div>\n";
|
53 |
$help .= '<div class="metabox-prefs">';
|
54 |
$help .= __('Version:', 'backwpup').' '.BACKWPUP_VERSION.' | ';
|
55 |
$help .= __('Author:', 'backwpup').' <a href="http://danielhuesken.de" target="_blank">Daniel Hüsken</a>';
|
56 |
$help .= "</div>\n";
|
57 |
return $help;
|
58 |
}
|
59 |
+
|
60 |
//Options Page
|
61 |
function backwpup_options_page() {
|
62 |
global $wpdb,$backwpup_message,$page_hook;
|
63 |
+
if (!current_user_can(10))
|
64 |
wp_die('No rights');
|
65 |
+
if(!empty($backwpup_message))
|
66 |
echo '<div id="message" class="updated fade"><p><strong>'.$backwpup_message.'</strong></p></div>';
|
67 |
switch($_REQUEST['action']) {
|
68 |
case 'edit':
|
82 |
case 'tools':
|
83 |
require_once(plugin_dir_path(__FILE__).'options-tools.php');
|
84 |
break;
|
85 |
+
case 'backups':
|
86 |
+
require_once(plugin_dir_path(__FILE__).'options-backups.php');
|
87 |
+
break;
|
88 |
case 'runnow':
|
89 |
$jobid = (int) $_GET['jobid'];
|
90 |
check_admin_referer('runnow-job_' . $jobid);
|
99 |
$jobs=get_option('backwpup_jobs');
|
100 |
require_once(plugin_dir_path(__FILE__).'options.php');
|
101 |
break;
|
102 |
+
}
|
103 |
}
|
104 |
+
|
105 |
//Options Page
|
106 |
function backwpup_options_load() {
|
107 |
global $wpdb,$backwpup_message;
|
108 |
+
if (!current_user_can(10))
|
109 |
wp_die('No rights');
|
110 |
//Css for Admin Section
|
111 |
wp_enqueue_style('BackWpup',plugins_url('css/options.css',__FILE__),'',BACKWPUP_VERSION,'screen');
|
113 |
//For save Options
|
114 |
require_once(plugin_dir_path(__FILE__).'options-save.php');
|
115 |
}
|
116 |
+
|
117 |
//delete Otions
|
118 |
function backwpup_plugin_uninstall() {
|
119 |
delete_option('backwpup');
|
134 |
$jobsettings['type']=implode('+',$todo);
|
135 |
if (empty($jobsettings['type']))
|
136 |
$jobsettings['type']='DB+FILE';
|
137 |
+
|
138 |
if (empty($jobsettings['name']) or !is_string($jobsettings['name']))
|
139 |
$jobsettings['name']= __('New');
|
140 |
+
|
141 |
+
if (!isset($jobsettings['activated']) or !is_bool($jobsettings['activated']))
|
142 |
$jobsettings['activated']=false;
|
143 |
+
|
144 |
if (!isset($jobsettings['scheduletime']) or !is_numeric($jobsettings['scheduletime']))
|
145 |
$jobsettings['scheduletime']=current_time('timestamp');
|
146 |
+
|
147 |
+
if (!isset($jobsettings['scheduleintervaltype']) or !is_int($jobsettings['scheduleintervaltype']))
|
148 |
$jobsettings['scheduleintervaltype']=3600;
|
149 |
if ($jobsettings['scheduleintervaltype']!=60 and $jobsettings['scheduleintervaltype']!=3600 and $jobsettings['scheduleintervaltype']!=86400)
|
150 |
$jobsettings['scheduleintervaltype']=3600;
|
151 |
+
|
152 |
if (!isset($jobsettings['scheduleintervalteimes']) or !is_int($jobsettings['scheduleintervalteimes']) or ($jobsettings['scheduleintervalteimes']<1 and $jobsettings['scheduleintervalteimes']>100))
|
153 |
$jobsettings['scheduleintervalteimes']=1;
|
154 |
+
|
155 |
$jobsettings['scheduleinterval']=$jobsettings['scheduleintervaltype']*$jobsettings['scheduleintervalteimes'];
|
156 |
+
|
157 |
if (!is_string($jobsettings['mailaddresslog']) or false === $pos=strpos($jobsettings['mailaddresslog'],'@') or false === strpos($jobsettings['mailaddresslog'],'.',$pos))
|
158 |
$jobsettings['mailaddresslog']=get_option('admin_email');
|
159 |
+
|
160 |
if (!isset($jobsettings['mailerroronly']) or !is_bool($jobsettings['mailerroronly']))
|
161 |
$jobsettings['mailerroronly']=true;
|
162 |
+
|
163 |
if (!isset($jobsettings['dbexclude']) or !is_array($jobsettings['dbexclude'])) {
|
164 |
$jobsettings['dbexclude']=array();
|
165 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
166 |
foreach ($tables as $table) {
|
167 |
if (substr($table,0,strlen($wpdb->prefix))!=$wpdb->prefix)
|
168 |
$jobsettings['dbexclude'][]=$table;
|
169 |
+
}
|
170 |
}
|
171 |
$tables=$wpdb->get_col('SHOW TABLES FROM `'.DB_NAME.'`');
|
172 |
foreach($jobsettings['dbexclude'] as $key => $value) {
|
174 |
unset($jobsettings['dbexclude'][$key]);
|
175 |
}
|
176 |
sort($jobsettings['dbexclude']);
|
177 |
+
|
178 |
if (!isset($jobsettings['dbshortinsert']) or !is_bool($jobsettings['dbshortinsert']))
|
179 |
$jobsettings['dbshortinsert']=false;
|
180 |
+
|
181 |
if (!isset($jobsettings['maintenance']) or !is_bool($jobsettings['maintenance']))
|
182 |
$jobsettings['maintenance']=false;
|
183 |
+
|
184 |
if (!isset($jobsettings['fileexclude']) or !is_string($jobsettings['fileexclude']))
|
185 |
$jobsettings['fileexclude']='';
|
186 |
$fileexclude=explode(',',$jobsettings['fileexclude']);
|
190 |
unset($fileexclude[$key]);
|
191 |
}
|
192 |
sort($fileexclude);
|
193 |
+
$jobsettings['fileexclude']=implode(',',$fileexclude);
|
194 |
+
|
195 |
if (!isset($jobsettings['dirinclude']) or !is_string($jobsettings['dirinclude']))
|
196 |
$jobsettings['dirinclude']='';
|
197 |
$dirinclude=explode(',',$jobsettings['dirinclude']);
|
201 |
unset($dirinclude[$key]);
|
202 |
}
|
203 |
sort($dirinclude);
|
204 |
+
$jobsettings['dirinclude']=implode(',',$dirinclude);
|
205 |
|
206 |
if (!isset($jobsettings['backuproot']) or !is_bool($jobsettings['backuproot']))
|
207 |
$jobsettings['backuproot']=true;
|
208 |
+
|
209 |
if (!isset($jobsettings['backupcontent']) or !is_bool($jobsettings['backupcontent']))
|
210 |
$jobsettings['backupcontent']=true;
|
211 |
+
|
212 |
if (!isset($jobsettings['backupplugins']) or !is_bool($jobsettings['backupplugins']))
|
213 |
$jobsettings['backupplugins']=true;
|
214 |
+
|
215 |
if (!isset($jobsettings['backupthemes']) or !is_bool($jobsettings['backupthemes']))
|
216 |
$jobsettings['backupthemes']=true;
|
217 |
|
262 |
unset($jobsettings['backupuploadsexcludedirs'][$key]);
|
263 |
}
|
264 |
sort($jobsettings['backupuploadsexcludedirs']);
|
265 |
+
|
266 |
$fileformarts=array('.zip','.tar.gz','tar.bz2','.tar');
|
267 |
if (!isset($jobsettings['fileformart']) or !in_array($jobsettings['fileformart'],$fileformarts))
|
268 |
$jobsettings['fileformart']='.zip';
|
269 |
+
|
270 |
if (!isset($jobsettings['mailefilesize']) or !is_float($jobsettings['mailefilesize']))
|
271 |
$jobsettings['mailefilesize']=0;
|
272 |
+
|
273 |
if (!isset($jobsettings['backupdir']) or (!is_dir($jobsettings['backupdir']) and !empty($jobsettings['backupdir']))) {
|
274 |
$rand = substr( md5( md5( SECURE_AUTH_KEY ) ), -5 );
|
275 |
+
$jobsettings['backupdir']=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'backwpup-'.$rand.'/';
|
276 |
}
|
277 |
$jobsettings['backupdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['backupdir']))));
|
278 |
if ($jobsettings['backupdir']=='/')
|
279 |
$jobsettings['backupdir']='';
|
280 |
+
|
281 |
if (!isset($jobsettings['maxbackups']) or !is_int($jobsettings['maxbackups']))
|
282 |
$jobsettings['maxbackups']=0;
|
283 |
+
|
284 |
if (!isset($jobsettings['ftphost']) or !is_string($jobsettings['ftphost']))
|
285 |
$jobsettings['ftphost']='';
|
286 |
+
|
287 |
+
if (!isset($jobsettings['ftpuser']) or !is_string($jobsettings['ftpuser']))
|
288 |
$jobsettings['ftpuser']='';
|
289 |
+
|
290 |
if (!isset($jobsettings['ftppass']) or !is_string($jobsettings['ftppass']))
|
291 |
$jobsettings['ftppass']='';
|
292 |
|
293 |
+
if (!isset($jobsettings['ftpdir']) or !is_string($jobsettings['ftpdir']) or $jobsettings['ftpdir']=='/')
|
294 |
$jobsettings['ftpdir']='';
|
295 |
$jobsettings['ftpdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['ftpdir']))));
|
296 |
+
if (substr($jobsettings['ftpdir'],0,1)!='/')
|
297 |
+
$jobsettings['ftpdir']='/'.$jobsettings['ftpdir'];
|
298 |
+
|
299 |
if (!isset($jobsettings['ftpmaxbackups']) or !is_int($jobsettings['ftpmaxbackups']))
|
300 |
$jobsettings['ftpmaxbackups']=0;
|
301 |
+
|
302 |
if (!isset($jobsettings['awsAccessKey']) or !is_string($jobsettings['awsAccessKey']))
|
303 |
$jobsettings['awsAccessKey']='';
|
304 |
+
|
305 |
if (!isset($jobsettings['awsSecretKey']) or !is_string($jobsettings['awsSecretKey']))
|
306 |
$jobsettings['awsSecretKey']='';
|
307 |
+
|
308 |
if (!isset($jobsettings['awsSSL']) or !is_bool($jobsettings['awsSSL']))
|
309 |
$jobsettings['awsSSL']=true;
|
310 |
+
|
311 |
if (!isset($jobsettings['awsBucket']) or !is_string($jobsettings['awsBucket']))
|
312 |
$jobsettings['awsBucket']='';
|
313 |
+
|
314 |
+
if (!isset($jobsettings['awsdir']) or !is_string($jobsettings['awsdir']) or $jobsettings['awsdir']=='/')
|
315 |
$jobsettings['awsdir']='';
|
316 |
$jobsettings['awsdir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['awsdir']))));
|
317 |
if (substr($jobsettings['awsdir'],0,1)=='/')
|
318 |
$jobsettings['awsdir']=substr($jobsettings['awsdir'],1);
|
319 |
+
|
320 |
if (!isset($jobsettings['awsmaxbackups']) or !is_int($jobsettings['awsmaxbackups']))
|
321 |
+
$jobsettings['awsmaxbackups']=0;
|
322 |
+
|
323 |
if (!is_string($jobsettings['mailaddress']) or false === $pos=strpos($jobsettings['mailaddress'],'@') or false === strpos($jobsettings['mailaddress'],'.',$pos))
|
324 |
$jobsettings['mailaddress']='';
|
325 |
|
326 |
return $jobsettings;
|
327 |
}
|
328 |
|
329 |
+
|
330 |
//On Plugin activate
|
331 |
function backwpup_plugin_activate() {
|
332 |
//add cron jobs
|
333 |
$jobs=get_option('backwpup_jobs');
|
334 |
+
if (is_array($jobs)) {
|
335 |
foreach ($jobs as $jobid => $jobvalue) {
|
336 |
+
if ($jobvalue['activated'] and wp_get_schedule('backwpup_cron',array('jobid'=>$jobid)) === false)
|
337 |
wp_schedule_event($jobvalue['scheduletime'], 'backwpup_int_'.$jobid, 'backwpup_cron',array('jobid'=>$jobid));
|
338 |
}
|
339 |
}
|
350 |
}
|
351 |
if (empty($cfg['dirlogs'])) {
|
352 |
$rand = substr( md5( md5( SECURE_AUTH_KEY ) ), -5 );
|
353 |
+
$cfg['dirlogs']=str_replace('\\','/',trailingslashit(WP_CONTENT_DIR)).'backwpup-'.$rand.'-logs/';
|
354 |
}
|
355 |
update_option('backwpup',$cfg);
|
356 |
}
|
357 |
+
|
358 |
//on Plugin deaktivate
|
359 |
function backwpup_plugin_deactivate() {
|
360 |
//remove cron jobs
|
361 |
$jobs=get_option('backwpup_jobs');
|
362 |
wp_clear_scheduled_hook('backwpup_cron');
|
363 |
}
|
364 |
+
|
365 |
//add edit setting to plugins page
|
366 |
function backwpup_plugin_options_link($links) {
|
367 |
$settings_link='<a href="admin.php?page=BackWPup" title="' . __('Go to Settings Page','backwpup') . '" class="edit">' . __('Settings') . '</a>';
|
368 |
+
array_unshift( $links, $settings_link );
|
369 |
return $links;
|
370 |
}
|
371 |
+
|
372 |
//add links on plugins page
|
373 |
function backwpup_plugin_links($links, $file) {
|
374 |
if ($file == BACKWPUP_PLUGIN_BASEDIR.'/backwpup.php') {
|
378 |
}
|
379 |
return $links;
|
380 |
}
|
381 |
+
|
382 |
//Add cron interval
|
383 |
function backwpup_intervals($schedules) {
|
384 |
$jobs=get_option('backwpup_jobs'); //Load Settings
|
387 |
if (!empty($jobvalue['scheduleinterval']))
|
388 |
$intervals['backwpup_int_'.$jobkey]=array('interval' => $jobvalue['scheduleinterval'], 'display' => __('BackWPup Job '.$jobkey, 'backwpup'));
|
389 |
}
|
390 |
+
if (is_array($intervals))
|
391 |
$schedules=array_merge($intervals,$schedules);
|
392 |
+
}
|
393 |
return $schedules;
|
394 |
}
|
395 |
|
400 |
extract($args, EXTR_SKIP );
|
401 |
else
|
402 |
$jobid=$args;
|
403 |
+
if (empty($jobid))
|
404 |
return false;
|
405 |
require_once('backwpup_dojob.php');
|
406 |
$backwpup_dojob= new backwpup_dojob($jobid);
|
407 |
unset($backwpup_dojob);
|
408 |
return $backwpup_logfile;
|
409 |
}
|
410 |
+
|
411 |
//file size
|
412 |
function backwpup_formatBytes($bytes, $precision = 2) {
|
413 |
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
416 |
$pow = min($pow, count($units) - 1);
|
417 |
$bytes /= pow(1024, $pow);
|
418 |
return round($bytes, $precision) . ' ' . $units[$pow];
|
419 |
+
}
|
420 |
+
|
421 |
//echo long backup type name
|
422 |
function backwpup_backup_types($type='',$echo=false) {
|
423 |
$typename='';
|
430 |
break;
|
431 |
case 'DB':
|
432 |
$typename.=__('Database Backup','backwpup')."<br />";
|
433 |
+
break;
|
434 |
case 'FILE':
|
435 |
$typename.=__('File Backup','backwpup')."<br />";
|
436 |
break;
|
445 |
} else {
|
446 |
$typename=array('WPEXP','DB','FILE','OPTIMIZE','CHECK');
|
447 |
}
|
448 |
+
|
449 |
+
if ($echo)
|
450 |
echo $typename;
|
451 |
else
|
452 |
return $typename;
|
453 |
}
|
454 |
+
|
455 |
//read log file header
|
456 |
function backwpup_read_logheader($logfile) {
|
457 |
+
$headers=array("backwpup_version" => "version","backwpup_logtime" => "logtime","backwpup_errors" => "errors","backwpup_warnings" => "warnings","backwpup_jobid" => "jobid","backwpup_jobname" => "name","backwpup_jobtype" => "type","backwpup_jobruntime" => "runtime","backwpup_backupfile" => "backupfile","backwpup_backupfilesize" => "backupfilesize");
|
458 |
if (!is_readable($logfile))
|
459 |
return false;
|
460 |
//Read file
|
470 |
else
|
471 |
$joddata[$field]='';
|
472 |
}
|
473 |
+
|
474 |
if (empty($joddata['logtime']))
|
475 |
$joddata['logtime']=filectime($logfile);
|
476 |
+
|
477 |
return $joddata;
|
478 |
}
|
479 |
+
|
480 |
+
|
481 |
//Dashboard widget
|
482 |
function backwpup_dashboard_output() {
|
483 |
global $wpdb;
|
493 |
closedir( $dir );
|
494 |
rsort($logfiles);
|
495 |
}
|
496 |
+
|
497 |
if (is_array($logfiles)) {
|
498 |
$count=0;
|
499 |
foreach ($logfiles as $logfile) {
|
500 |
$logdata=backwpup_read_logheader($cfg['dirlogs'].'/'.$logfile);
|
501 |
echo '<a href="'.wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile).'" title="'.__('View Log','backwpup').'">'.date_i18n(get_option('date_format'),$logdata['logtime']).' '.date_i18n(get_option('time_format'),$logdata['logtime']).': <i>';
|
502 |
+
if (empty($logdata['name']))
|
503 |
echo $logdata['type'];
|
504 |
else
|
505 |
echo $logdata['name'];
|
506 |
echo '</i>';
|
507 |
+
if($logdata['errors']>0 or $logdata['warnings']>0) {
|
508 |
if ($logdata['errors']>0)
|
509 |
+
echo ' <span style="color:red;">'.$logdata['errors'].' '.__('ERROR(S)','backwpup').'</span>';
|
510 |
if ($logdata['warnings']>0)
|
511 |
+
echo ' <span style="color:yellow;">'.$logdata['warnings'].' '.__('WARNING(S)','backwpup').'</span>';
|
512 |
+
} else {
|
513 |
+
echo ' <span style="color:green;">'.__('OK','backwpup').'</span>';
|
514 |
+
}
|
515 |
echo '</a><br />';
|
516 |
$count++;
|
517 |
if ($count>=5)
|
522 |
}
|
523 |
$jobs=get_option('backwpup_jobs');
|
524 |
echo '<strong>'.__('Scheduled Jobs:','backwpup').'</strong><br />';
|
525 |
+
if (is_array($jobs)) {
|
526 |
foreach ($jobs as $jobid => $jobvalue) {
|
527 |
if (wp_next_scheduled('backwpup_cron',array('jobid'=>$jobid))) {
|
528 |
echo '<a href="'.wp_nonce_url('admin.php?page=BackWPup&action=edit&jobid='.$jobid, 'edit-job').'" title="'.__('Edit Job','backwpup').'">';
|
539 |
echo '<i>'.__('none','backwpup').'</i><br />';
|
540 |
}
|
541 |
}
|
542 |
+
|
543 |
//add dashboard widget
|
544 |
function backwpup_add_dashboard() {
|
545 |
+
wp_add_dashboard_widget( 'backwpup_dashboard_widget', 'BackWPup', 'backwpup_dashboard_output' );
|
546 |
}
|
547 |
+
|
548 |
//turn cache off
|
549 |
function backwpup_meta_no_cache() {
|
550 |
echo "<meta http-equiv=\"expires\" content=\"0\" />\n";
|
551 |
echo "<meta http-equiv=\"pragma\" content=\"no-cache\" />\n";
|
552 |
echo "<meta http-equiv=\"cache-control\" content=\"no-cache\" />\n";
|
553 |
}
|
554 |
+
|
555 |
function backwpup_send_no_cache_header() {
|
556 |
header("Expires: 0");
|
557 |
header("Cache-Control: no-cache, must-revalidate");
|
574 |
// $dir is absolute, $upload_path is (maybe) relative to ABSPATH
|
575 |
$dir = path_join( ABSPATH, $dir );
|
576 |
}
|
577 |
+
}
|
578 |
if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
|
579 |
$dir = ABSPATH . UPLOADS;
|
580 |
}
|
584 |
$dir = untrailingslashit(BLOGUPLOADDIR);
|
585 |
}
|
586 |
}
|
587 |
+
|
588 |
return str_replace('\\','/',trailingslashit($dir));
|
589 |
}
|
590 |
+
|
591 |
function backwpup_get_exclude_wp_dirs($folder) {
|
592 |
$folder=trailingslashit(str_replace('\\','/',$folder));
|
593 |
$excludedir=array();
|
603 |
$excludedir[]=backwpup_get_upload_dir();
|
604 |
//Exclude Backup dirs
|
605 |
$jobs=get_option('backwpup_jobs');
|
606 |
+
foreach((array)$jobs as $jobsvale) {
|
607 |
if (!empty($jobsvale['backupdir']) and $jobsvale['backupdir']!='/')
|
608 |
$excludedir[]=trailingslashit(str_replace('\\','/',$jobsvale['backupdir']));
|
609 |
}
|
610 |
return $excludedir;
|
611 |
}
|
612 |
+
|
613 |
+
//ajax/normal get backup files and infos
|
614 |
+
function backwpup_get_backup_files() {
|
615 |
+
$jobs=get_option('backwpup_jobs'); //Load jobs
|
616 |
+
$filecounter=0;
|
617 |
+
$files=array();
|
618 |
+
if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
|
619 |
+
if (!class_exists('S3'))
|
620 |
+
require_once(plugin_dir_path(__FILE__).'libs/S3.php');
|
621 |
+
}
|
622 |
+
|
623 |
+
if (!is_array($jobs)) //return is Jobs empty
|
624 |
+
return false;
|
625 |
|
626 |
+
foreach ($jobs as $jobid => $jobvalue) { //go job by job
|
627 |
+
$jobvalue=backwpup_check_job_vars($jobvalue); //Check job values
|
628 |
+
$todo=explode('+',$jobvalue['type']); //only for backup jobs
|
629 |
+
if (!in_array('FILE',$todo) and !in_array('DB',$todo) and !in_array('WPEXP',$todo))
|
630 |
+
continue;
|
631 |
+
|
632 |
+
//Get files/filinfo in backup folder
|
633 |
+
if (!empty($jobvalue['backupdir'])) {
|
634 |
+
if ( $dir = @opendir( $jobvalue['backupdir'] ) ) {
|
635 |
+
while (($file = readdir( $dir ) ) !== false ) {
|
636 |
+
if (substr($file,0,1)=='.' or strtolower(substr($file,-4))=='.zip' or !(strtolower(substr($file,-4))=='.tar' or strtolower(substr($file,-7))=='.tar.gz' or strtolower(substr($file,-4))=='.tar.bz2'))
|
637 |
+
continue;
|
638 |
+
if (is_file($jobvalue['backupdir'].$file)) {
|
639 |
+
$files[$filecounter]['type']='FOLDER';
|
640 |
+
$files[$filecounter]['jobid']=$jobid;
|
641 |
+
$files[$filecounter]['file']=$jobvalue['backupdir'].$file;
|
642 |
+
$files[$filecounter]['filename']=$file;
|
643 |
+
$files[$filecounter]['downloadurl']=wp_nonce_url('admin.php?page=BackWPup&action=download&file='.$jobvalue['backupdir'].$file, 'download-backup_'.$file);
|
644 |
+
$files[$filecounter]['filesize']=filesize($jobvalue['backupdir'].$file);
|
645 |
+
$files[$filecounter]['time']=filemtime($jobvalue['backupdir'].$file);
|
646 |
+
$filecounter++;
|
647 |
+
}
|
648 |
+
}
|
649 |
+
closedir( $dir );
|
650 |
+
}
|
651 |
+
}
|
652 |
+
//Get files/filinfo from S3
|
653 |
+
if (class_exists('S3')) {
|
654 |
+
if (!empty($jobvalue['awsAccessKey']) and !empty($jobvalue['awsSecretKey']) and !empty($jobvalue['awsBucket'])) {
|
655 |
+
$s3 = new S3($jobvalue['awsAccessKey'], $jobvalue['awsSecretKey'], $jobvalue['awsSSL']);
|
656 |
+
if (($contents = $s3->getBucket($jobvalue['awsBucket'],$jobvalue['awsdir'])) !== false) {
|
657 |
+
foreach ($contents as $object) {
|
658 |
+
if (strtolower(substr($object['name'],-4))=='.zip' or strtolower(substr($object['name'],-4))=='.tar' or strtolower(substr($object['name'],-7))=='.tar.gz' or strtolower(substr($object['name'],-4))=='.tar.bz2') {
|
659 |
+
$files[$filecounter]['type']='S3';
|
660 |
+
$files[$filecounter]['jobid']=$jobid;
|
661 |
+
$files[$filecounter]['file']=$object['name'];
|
662 |
+
$files[$filecounter]['filename']=basename($object['name']);
|
663 |
+
$files[$filecounter]['downloadurl']=wp_nonce_url('admin.php?page=BackWPup&action=downloads3&file='.$object['name'].'&jobid='.$jobid, 'downloads3-backup_'.$object['name']);
|
664 |
+
$files[$filecounter]['filesize']=$object['size'];
|
665 |
+
$files[$filecounter]['time']=$object['time'];
|
666 |
+
$filecounter++;
|
667 |
+
}
|
668 |
+
}
|
669 |
+
}
|
670 |
+
}
|
671 |
+
}
|
672 |
+
//Get files/filinfo from FTP
|
673 |
+
if (!empty($jobvalue['ftphost']) and !empty($jobvalue['ftpuser']) and !empty($jobvalue['ftppass'])) {
|
674 |
+
$ftpport=21;
|
675 |
+
$ftphost=$jobvalue['ftphost'];
|
676 |
+
if (false !== strpos($jobvalue['ftphost'],':')) //look for port
|
677 |
+
list($ftphost,$ftpport)=explode(':',$jobvalue,2);
|
678 |
+
|
679 |
+
$SSL=false;
|
680 |
+
if (function_exists('ftp_ssl_connect')) { //make SSL FTP connection
|
681 |
+
$ftp_conn_id = ftp_ssl_connect($ftphost,$ftpport,10);
|
682 |
+
if ($ftp_conn_id)
|
683 |
+
$SSL=true;
|
684 |
+
}
|
685 |
+
if (!$ftp_conn_id) { //make normal FTP conection if SSL not work
|
686 |
+
$ftp_conn_id = ftp_connect($ftphost,$ftpport,10);
|
687 |
+
}
|
688 |
+
if ($ftp_conn_id) {
|
689 |
+
//FTP Login
|
690 |
+
$loginok=false;
|
691 |
+
if (@ftp_login($ftp_conn_id, $jobvalue['ftpuser'], base64_decode($jobvalue['ftppass']))) {
|
692 |
+
$loginok=true;
|
693 |
+
} else { //if PHP ftp login don't work use raw login
|
694 |
+
if (substr(trim(ftp_raw($ftp_conn_id,'USER '.$jobvalue['ftpuser'])),0,3)<400) {
|
695 |
+
if (substr(trim(ftp_raw($ftp_conn_id,'PASS '.base64_decode($jobvalue['ftppass']))),0,3)<400) {
|
696 |
+
$loginok=true;
|
697 |
+
}
|
698 |
+
}
|
699 |
+
}
|
700 |
+
}
|
701 |
+
if ($loginok) {
|
702 |
+
ftp_pasv($ftp_conn_id, true);
|
703 |
+
if ($ftpfilelist=ftp_nlist($ftp_conn_id, $jobvalue['ftpdir'])) {
|
704 |
+
foreach($ftpfilelist as $ftpfiles) {
|
705 |
+
if (basename($ftpfiles)=='.' or basename($ftpfiles)=='..' or substr(basename($ftpfiles),0,1)=='.' or !(strtolower(substr($ftpfiles,-4))=='.zip' or strtolower(substr($ftpfiles,-4))=='.tar' or strtolower(substr($ftpfiles,-7))=='.tar.gz' or strtolower(substr($ftpfiles,-4))=='.tar.bz2'))
|
706 |
+
continue;
|
707 |
+
$files[$filecounter]['type']='FTP';
|
708 |
+
$files[$filecounter]['jobid']=$jobid;
|
709 |
+
$files[$filecounter]['file']=$ftpfiles;
|
710 |
+
$files[$filecounter]['filename']=basename($ftpfiles);
|
711 |
+
$files[$filecounter]['downloadurl']="ftp://".$jobvalue['ftpuser'].":".base64_decode($jobvalue['ftppass'])."@".$jobvalue['ftphost'].$ftpfiles;
|
712 |
+
$files[$filecounter]['filesize']=ftp_size($ftp_conn_id,$ftpfiles);
|
713 |
+
$filecounter++;
|
714 |
+
}
|
715 |
+
}
|
716 |
+
}
|
717 |
+
}
|
718 |
+
}
|
719 |
+
//Sort list
|
720 |
+
$tmp = Array();
|
721 |
+
foreach($files as &$ma)
|
722 |
+
$tmp[] = &$ma["filename"];
|
723 |
+
array_multisort($tmp, SORT_DESC, $files);
|
724 |
+
return $files;
|
725 |
+
}
|
726 |
+
|
727 |
//ajax/normal get buckests select box
|
728 |
function backwpup_get_aws_buckets($args='') {
|
729 |
if (is_array($args)) {
|
743 |
if (empty($awsSecretKey)) {
|
744 |
echo '<span id="awsBucket" style="color:red;">'.__('Missing Secret Access Key!','backwpup').'</span>';
|
745 |
die();
|
746 |
+
}
|
747 |
$s3 = new S3($awsAccessKey, $awsSecretKey, false);
|
748 |
$buckets=@$s3->listBuckets();
|
749 |
if (!is_array($buckets)) {
|
750 |
echo '<span id="awsBucket" style="color:red;">'.__('No Buckets found! Or wrong Keys!','backwpup').'</span>';
|
751 |
die();
|
752 |
+
}
|
753 |
echo '<select name="awsBucket" id="awsBucket">';
|
754 |
foreach ($buckets as $bucket) {
|
755 |
echo "<option ".selected(strtolower($selected),strtolower($bucket),false).">".$bucket."</option>";
|
758 |
if ($ajax)
|
759 |
die();
|
760 |
}
|
761 |
+
|
762 |
// add all action and so on only if plugin loaded.
|
763 |
function backwpup_init() {
|
764 |
//Disabele WP_Corn
|
768 |
//add Menu
|
769 |
add_action('admin_menu', 'backwpup_menu_entry');
|
770 |
//Additional links on the plugin page
|
771 |
+
if (current_user_can(10))
|
772 |
add_filter('plugin_action_links_'.BACKWPUP_PLUGIN_BASEDIR.'/backwpup.php', 'backwpup_plugin_options_link');
|
773 |
+
if (current_user_can('install_plugins'))
|
774 |
add_filter('plugin_row_meta', 'backwpup_plugin_links',10,2);
|
775 |
//add cron intervals
|
776 |
add_filter('cron_schedules', 'backwpup_intervals');
|
777 |
//Actions for Cron job
|
778 |
add_action('backwpup_cron', 'backwpup_dojob');
|
779 |
//add Dashboard widget
|
780 |
+
if (current_user_can(10))
|
781 |
add_action('wp_dashboard_setup', 'backwpup_add_dashboard');
|
782 |
// add ajax function
|
783 |
add_action('wp_ajax_backwpup_get_aws_buckets', 'backwpup_get_aws_buckets');
|
784 |
+
}
|
785 |
|
786 |
?>
|
app/libs/S3.php
CHANGED
@@ -1,1365 +1,1365 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* $Id: S3.php 47 2009-07-20 01:25:40Z don.schonknecht $
|
4 |
-
*
|
5 |
-
* Copyright (c) 2008, 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.4.0
|
36 |
-
*/
|
37 |
-
class S3 {
|
38 |
-
// ACL flags
|
39 |
-
const ACL_PRIVATE = 'private';
|
40 |
-
const ACL_PUBLIC_READ = 'public-read';
|
41 |
-
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
|
42 |
-
const ACL_AUTHENTICATED_READ = 'authenticated-read';
|
43 |
-
|
44 |
-
public static $useSSL = true;
|
45 |
-
|
46 |
-
private static $__accessKey; // AWS Access key
|
47 |
-
private static $__secretKey; // AWS Secret key
|
48 |
-
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Constructor - if you're not using the class statically
|
52 |
-
*
|
53 |
-
* @param string $accessKey Access key
|
54 |
-
* @param string $secretKey Secret key
|
55 |
-
* @param boolean $useSSL Enable SSL
|
56 |
-
* @return void
|
57 |
-
*/
|
58 |
-
public function __construct($accessKey = null, $secretKey = null, $useSSL = true) {
|
59 |
-
if ($accessKey !== null && $secretKey !== null)
|
60 |
-
self::setAuth($accessKey, $secretKey);
|
61 |
-
self::$useSSL = $useSSL;
|
62 |
-
}
|
63 |
-
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Set AWS access key and secret key
|
67 |
-
*
|
68 |
-
* @param string $accessKey Access key
|
69 |
-
* @param string $secretKey Secret key
|
70 |
-
* @return void
|
71 |
-
*/
|
72 |
-
public static function setAuth($accessKey, $secretKey) {
|
73 |
-
self::$__accessKey = $accessKey;
|
74 |
-
self::$__secretKey = $secretKey;
|
75 |
-
}
|
76 |
-
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Get a list of buckets
|
80 |
-
*
|
81 |
-
* @param boolean $detailed Returns detailed bucket list when true
|
82 |
-
* @return array | false
|
83 |
-
*/
|
84 |
-
public static function listBuckets($detailed = false) {
|
85 |
-
$rest = new S3Request('GET', '', '');
|
86 |
-
$rest = $rest->getResponse();
|
87 |
-
if ($rest->error === false && $rest->code !== 200)
|
88 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
89 |
-
if ($rest->error !== false) {
|
90 |
-
trigger_error(sprintf("S3::listBuckets(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
91 |
-
return false;
|
92 |
-
}
|
93 |
-
$results = array();
|
94 |
-
if (!isset($rest->body->Buckets)) return $results;
|
95 |
-
|
96 |
-
if ($detailed) {
|
97 |
-
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
|
98 |
-
$results['owner'] = array(
|
99 |
-
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
|
100 |
-
);
|
101 |
-
$results['buckets'] = array();
|
102 |
-
foreach ($rest->body->Buckets->Bucket as $b)
|
103 |
-
$results['buckets'][] = array(
|
104 |
-
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
|
105 |
-
);
|
106 |
-
} else
|
107 |
-
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
|
108 |
-
|
109 |
-
return $results;
|
110 |
-
}
|
111 |
-
|
112 |
-
|
113 |
-
/*
|
114 |
-
* Get contents for a bucket
|
115 |
-
*
|
116 |
-
* If maxKeys is null this method will loop through truncated result sets
|
117 |
-
*
|
118 |
-
* @param string $bucket Bucket name
|
119 |
-
* @param string $prefix Prefix
|
120 |
-
* @param string $marker Marker (last file listed)
|
121 |
-
* @param string $maxKeys Max keys (maximum number of keys to return)
|
122 |
-
* @param string $delimiter Delimiter
|
123 |
-
* @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
|
124 |
-
* @return array | false
|
125 |
-
*/
|
126 |
-
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false) {
|
127 |
-
$rest = new S3Request('GET', $bucket, '');
|
128 |
-
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
129 |
-
if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
|
130 |
-
if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
|
131 |
-
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
132 |
-
$response = $rest->getResponse();
|
133 |
-
if ($response->error === false && $response->code !== 200)
|
134 |
-
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
|
135 |
-
if ($response->error !== false) {
|
136 |
-
trigger_error(sprintf("S3::getBucket(): [%s] %s", $response->error['code'], $response->error['message']), E_USER_WARNING);
|
137 |
-
return false;
|
138 |
-
}
|
139 |
-
|
140 |
-
$results = array();
|
141 |
-
|
142 |
-
$nextMarker = null;
|
143 |
-
if (isset($response->body, $response->body->Contents))
|
144 |
-
foreach ($response->body->Contents as $c) {
|
145 |
-
$results[(string)$c->Key] = array(
|
146 |
-
'name' => (string)$c->Key,
|
147 |
-
'time' => strtotime((string)$c->LastModified),
|
148 |
-
'size' => (int)$c->Size,
|
149 |
-
'hash' => substr((string)$c->ETag, 1, -1)
|
150 |
-
);
|
151 |
-
$nextMarker = (string)$c->Key;
|
152 |
-
}
|
153 |
-
|
154 |
-
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
155 |
-
foreach ($response->body->CommonPrefixes as $c)
|
156 |
-
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
157 |
-
|
158 |
-
if (isset($response->body, $response->body->IsTruncated) &&
|
159 |
-
(string)$response->body->IsTruncated == 'false') return $results;
|
160 |
-
|
161 |
-
if (isset($response->body, $response->body->NextMarker))
|
162 |
-
$nextMarker = (string)$response->body->NextMarker;
|
163 |
-
|
164 |
-
// Loop through truncated results if maxKeys isn't specified
|
165 |
-
if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
|
166 |
-
do {
|
167 |
-
$rest = new S3Request('GET', $bucket, '');
|
168 |
-
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
169 |
-
$rest->setParameter('marker', $nextMarker);
|
170 |
-
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
171 |
-
|
172 |
-
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
|
173 |
-
|
174 |
-
if (isset($response->body, $response->body->Contents))
|
175 |
-
foreach ($response->body->Contents as $c) {
|
176 |
-
$results[(string)$c->Key] = array(
|
177 |
-
'name' => (string)$c->Key,
|
178 |
-
'time' => strtotime((string)$c->LastModified),
|
179 |
-
'size' => (int)$c->Size,
|
180 |
-
'hash' => substr((string)$c->ETag, 1, -1)
|
181 |
-
);
|
182 |
-
$nextMarker = (string)$c->Key;
|
183 |
-
}
|
184 |
-
|
185 |
-
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
186 |
-
foreach ($response->body->CommonPrefixes as $c)
|
187 |
-
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
188 |
-
|
189 |
-
if (isset($response->body, $response->body->NextMarker))
|
190 |
-
$nextMarker = (string)$response->body->NextMarker;
|
191 |
-
|
192 |
-
} while ($response !== false && (string)$response->body->IsTruncated == 'true');
|
193 |
-
|
194 |
-
return $results;
|
195 |
-
}
|
196 |
-
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Put a bucket
|
200 |
-
*
|
201 |
-
* @param string $bucket Bucket name
|
202 |
-
* @param constant $acl ACL flag
|
203 |
-
* @param string $location Set as "EU" to create buckets hosted in Europe
|
204 |
-
* @return boolean
|
205 |
-
*/
|
206 |
-
public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false) {
|
207 |
-
$rest = new S3Request('PUT', $bucket, '');
|
208 |
-
$rest->setAmzHeader('x-amz-acl', $acl);
|
209 |
-
|
210 |
-
if ($location !== false) {
|
211 |
-
$dom = new DOMDocument;
|
212 |
-
$createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
|
213 |
-
$locationConstraint = $dom->createElement('LocationConstraint', strtoupper($location));
|
214 |
-
$createBucketConfiguration->appendChild($locationConstraint);
|
215 |
-
$dom->appendChild($createBucketConfiguration);
|
216 |
-
$rest->data = $dom->saveXML();
|
217 |
-
$rest->size = strlen($rest->data);
|
218 |
-
$rest->setHeader('Content-Type', 'application/xml');
|
219 |
-
}
|
220 |
-
$rest = $rest->getResponse();
|
221 |
-
|
222 |
-
if ($rest->error === false && $rest->code !== 200)
|
223 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
224 |
-
if ($rest->error !== false) {
|
225 |
-
trigger_error(sprintf("S3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
|
226 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
227 |
-
return false;
|
228 |
-
}
|
229 |
-
return true;
|
230 |
-
}
|
231 |
-
|
232 |
-
|
233 |
-
/**
|
234 |
-
* Delete an empty bucket
|
235 |
-
*
|
236 |
-
* @param string $bucket Bucket name
|
237 |
-
* @return boolean
|
238 |
-
*/
|
239 |
-
public static function deleteBucket($bucket) {
|
240 |
-
$rest = new S3Request('DELETE', $bucket);
|
241 |
-
$rest = $rest->getResponse();
|
242 |
-
if ($rest->error === false && $rest->code !== 204)
|
243 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
244 |
-
if ($rest->error !== false) {
|
245 |
-
trigger_error(sprintf("S3::deleteBucket({$bucket}): [%s] %s",
|
246 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
247 |
-
return false;
|
248 |
-
}
|
249 |
-
return true;
|
250 |
-
}
|
251 |
-
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Create input info array for putObject()
|
255 |
-
*
|
256 |
-
* @param string $file Input file
|
257 |
-
* @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
|
258 |
-
* @return array | false
|
259 |
-
*/
|
260 |
-
public static function inputFile($file, $md5sum = true) {
|
261 |
-
if (!file_exists($file) || !is_file($file) || !is_readable($file)) {
|
262 |
-
trigger_error('S3::inputFile(): Unable to open input file: '.$file, E_USER_WARNING);
|
263 |
-
return false;
|
264 |
-
}
|
265 |
-
return array('file' => $file, 'size' => filesize($file),
|
266 |
-
'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum :
|
267 |
-
base64_encode(md5_file($file, true))) : '');
|
268 |
-
}
|
269 |
-
|
270 |
-
|
271 |
-
/**
|
272 |
-
* Create input array info for putObject() with a resource
|
273 |
-
*
|
274 |
-
* @param string $resource Input resource to read from
|
275 |
-
* @param integer $bufferSize Input byte size
|
276 |
-
* @param string $md5sum MD5 hash to send (optional)
|
277 |
-
* @return array | false
|
278 |
-
*/
|
279 |
-
public static function inputResource(&$resource, $bufferSize, $md5sum = '') {
|
280 |
-
if (!is_resource($resource) || $bufferSize < 0) {
|
281 |
-
trigger_error('S3::inputResource(): Invalid resource or buffer size', E_USER_WARNING);
|
282 |
-
return false;
|
283 |
-
}
|
284 |
-
$input = array('size' => $bufferSize, 'md5sum' => $md5sum);
|
285 |
-
$input['fp'] =& $resource;
|
286 |
-
return $input;
|
287 |
-
}
|
288 |
-
|
289 |
-
|
290 |
-
/**
|
291 |
-
* Put an object
|
292 |
-
*
|
293 |
-
* @param mixed $input Input data
|
294 |
-
* @param string $bucket Bucket name
|
295 |
-
* @param string $uri Object URI
|
296 |
-
* @param constant $acl ACL constant
|
297 |
-
* @param array $metaHeaders Array of x-amz-meta-* headers
|
298 |
-
* @param array $requestHeaders Array of request headers or content type as a string
|
299 |
-
* @return boolean
|
300 |
-
*/
|
301 |
-
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
|
302 |
-
if ($input === false) return false;
|
303 |
-
$rest = new S3Request('PUT', $bucket, $uri);
|
304 |
-
|
305 |
-
if (is_string($input)) $input = array(
|
306 |
-
'data' => $input, 'size' => strlen($input),
|
307 |
-
'md5sum' => base64_encode(md5($input, true))
|
308 |
-
);
|
309 |
-
|
310 |
-
// Data
|
311 |
-
if (isset($input['fp']))
|
312 |
-
$rest->fp =& $input['fp'];
|
313 |
-
elseif (isset($input['file']))
|
314 |
-
$rest->fp = @fopen($input['file'], 'rb');
|
315 |
-
elseif (isset($input['data']))
|
316 |
-
$rest->data = $input['data'];
|
317 |
-
|
318 |
-
// Content-Length (required)
|
319 |
-
if (isset($input['size']) && $input['size'] >= 0)
|
320 |
-
$rest->size = $input['size'];
|
321 |
-
else {
|
322 |
-
if (isset($input['file']))
|
323 |
-
$rest->size = filesize($input['file']);
|
324 |
-
elseif (isset($input['data']))
|
325 |
-
$rest->size = strlen($input['data']);
|
326 |
-
}
|
327 |
-
|
328 |
-
// Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
|
329 |
-
if (is_array($requestHeaders))
|
330 |
-
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
331 |
-
elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
|
332 |
-
$input['type'] = $requestHeaders;
|
333 |
-
|
334 |
-
// Content-Type
|
335 |
-
if (!isset($input['type'])) {
|
336 |
-
if (isset($requestHeaders['Content-Type']))
|
337 |
-
$input['type'] =& $requestHeaders['Content-Type'];
|
338 |
-
elseif (isset($input['file']))
|
339 |
-
$input['type'] = self::__getMimeType($input['file']);
|
340 |
-
else
|
341 |
-
$input['type'] = 'application/octet-stream';
|
342 |
-
}
|
343 |
-
|
344 |
-
// We need to post with Content-Length and Content-Type, MD5 is optional
|
345 |
-
if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false)) {
|
346 |
-
$rest->setHeader('Content-Type', $input['type']);
|
347 |
-
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
|
348 |
-
|
349 |
-
$rest->setAmzHeader('x-amz-acl', $acl);
|
350 |
-
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
351 |
-
$rest->getResponse();
|
352 |
-
} else
|
353 |
-
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
|
354 |
-
|
355 |
-
if ($rest->response->error === false && $rest->response->code !== 200)
|
356 |
-
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
357 |
-
if ($rest->response->error !== false) {
|
358 |
-
trigger_error(sprintf("S3::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
|
359 |
-
return false;
|
360 |
-
}
|
361 |
-
return true;
|
362 |
-
}
|
363 |
-
|
364 |
-
|
365 |
-
/**
|
366 |
-
* Put an object from a file (legacy function)
|
367 |
-
*
|
368 |
-
* @param string $file Input file path
|
369 |
-
* @param string $bucket Bucket name
|
370 |
-
* @param string $uri Object URI
|
371 |
-
* @param constant $acl ACL constant
|
372 |
-
* @param array $metaHeaders Array of x-amz-meta-* headers
|
373 |
-
* @param string $contentType Content type
|
374 |
-
* @return boolean
|
375 |
-
*/
|
376 |
-
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null) {
|
377 |
-
return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
|
378 |
-
}
|
379 |
-
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Put an object from a string (legacy function)
|
383 |
-
*
|
384 |
-
* @param string $string Input data
|
385 |
-
* @param string $bucket Bucket name
|
386 |
-
* @param string $uri Object URI
|
387 |
-
* @param constant $acl ACL constant
|
388 |
-
* @param array $metaHeaders Array of x-amz-meta-* headers
|
389 |
-
* @param string $contentType Content type
|
390 |
-
* @return boolean
|
391 |
-
*/
|
392 |
-
public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') {
|
393 |
-
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
|
394 |
-
}
|
395 |
-
|
396 |
-
|
397 |
-
/**
|
398 |
-
* Get an object
|
399 |
-
*
|
400 |
-
* @param string $bucket Bucket name
|
401 |
-
* @param string $uri Object URI
|
402 |
-
* @param mixed $saveTo Filename or resource to write to
|
403 |
-
* @return mixed
|
404 |
-
*/
|
405 |
-
public static function getObject($bucket, $uri, $saveTo = false) {
|
406 |
-
$rest = new S3Request('GET', $bucket, $uri);
|
407 |
-
if ($saveTo !== false) {
|
408 |
-
if (is_resource($saveTo))
|
409 |
-
$rest->fp =& $saveTo;
|
410 |
-
else
|
411 |
-
if (($rest->fp = @fopen($saveTo, 'wb')) !== false)
|
412 |
-
$rest->file = realpath($saveTo);
|
413 |
-
else
|
414 |
-
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
|
415 |
-
}
|
416 |
-
if ($rest->response->error === false) $rest->getResponse();
|
417 |
-
|
418 |
-
if ($rest->response->error === false && $rest->response->code !== 200)
|
419 |
-
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
420 |
-
if ($rest->response->error !== false) {
|
421 |
-
trigger_error(sprintf("S3::getObject({$bucket}, {$uri}): [%s] %s",
|
422 |
-
$rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
|
423 |
-
return false;
|
424 |
-
}
|
425 |
-
return $rest->response;
|
426 |
-
}
|
427 |
-
|
428 |
-
|
429 |
-
/**
|
430 |
-
* Get object information
|
431 |
-
*
|
432 |
-
* @param string $bucket Bucket name
|
433 |
-
* @param string $uri Object URI
|
434 |
-
* @param boolean $returnInfo Return response information
|
435 |
-
* @return mixed | false
|
436 |
-
*/
|
437 |
-
public static function getObjectInfo($bucket, $uri, $returnInfo = true) {
|
438 |
-
$rest = new S3Request('HEAD', $bucket, $uri);
|
439 |
-
$rest = $rest->getResponse();
|
440 |
-
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
|
441 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
442 |
-
if ($rest->error !== false) {
|
443 |
-
trigger_error(sprintf("S3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
|
444 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
445 |
-
return false;
|
446 |
-
}
|
447 |
-
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
|
448 |
-
}
|
449 |
-
|
450 |
-
|
451 |
-
/**
|
452 |
-
* Copy an object
|
453 |
-
*
|
454 |
-
* @param string $bucket Source bucket name
|
455 |
-
* @param string $uri Source object URI
|
456 |
-
* @param string $bucket Destination bucket name
|
457 |
-
* @param string $uri Destination object URI
|
458 |
-
* @param constant $acl ACL constant
|
459 |
-
* @param array $metaHeaders Optional array of x-amz-meta-* headers
|
460 |
-
* @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
|
461 |
-
* @return mixed | false
|
462 |
-
*/
|
463 |
-
public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
|
464 |
-
$rest = new S3Request('PUT', $bucket, $uri);
|
465 |
-
$rest->setHeader('Content-Length', 0);
|
466 |
-
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
467 |
-
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
468 |
-
$rest->setAmzHeader('x-amz-acl', $acl);
|
469 |
-
$rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, $srcUri));
|
470 |
-
if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
|
471 |
-
$rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
|
472 |
-
$rest = $rest->getResponse();
|
473 |
-
if ($rest->error === false && $rest->code !== 200)
|
474 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
475 |
-
if ($rest->error !== false) {
|
476 |
-
trigger_error(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
|
477 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
478 |
-
return false;
|
479 |
-
}
|
480 |
-
return isset($rest->body->LastModified, $rest->body->ETag) ? array(
|
481 |
-
'time' => strtotime((string)$rest->body->LastModified),
|
482 |
-
'hash' => substr((string)$rest->body->ETag, 1, -1)
|
483 |
-
) : false;
|
484 |
-
}
|
485 |
-
|
486 |
-
|
487 |
-
/**
|
488 |
-
* Set logging for a bucket
|
489 |
-
*
|
490 |
-
* @param string $bucket Bucket name
|
491 |
-
* @param string $targetBucket Target bucket (where logs are stored)
|
492 |
-
* @param string $targetPrefix Log prefix (e,g; domain.com-)
|
493 |
-
* @return boolean
|
494 |
-
*/
|
495 |
-
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null) {
|
496 |
-
// The S3 log delivery group has to be added to the target bucket's ACP
|
497 |
-
if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false) {
|
498 |
-
// Only add permissions to the target bucket when they do not exist
|
499 |
-
$aclWriteSet = false;
|
500 |
-
$aclReadSet = false;
|
501 |
-
foreach ($acp['acl'] as $acl)
|
502 |
-
if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery') {
|
503 |
-
if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
|
504 |
-
elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
|
505 |
-
}
|
506 |
-
if (!$aclWriteSet) $acp['acl'][] = array(
|
507 |
-
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
|
508 |
-
);
|
509 |
-
if (!$aclReadSet) $acp['acl'][] = array(
|
510 |
-
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
|
511 |
-
);
|
512 |
-
if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
|
513 |
-
}
|
514 |
-
|
515 |
-
$dom = new DOMDocument;
|
516 |
-
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
|
517 |
-
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
|
518 |
-
if ($targetBucket !== null) {
|
519 |
-
if ($targetPrefix == null) $targetPrefix = $bucket . '-';
|
520 |
-
$loggingEnabled = $dom->createElement('LoggingEnabled');
|
521 |
-
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
|
522 |
-
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
|
523 |
-
// TODO: Add TargetGrants?
|
524 |
-
$bucketLoggingStatus->appendChild($loggingEnabled);
|
525 |
-
}
|
526 |
-
$dom->appendChild($bucketLoggingStatus);
|
527 |
-
|
528 |
-
$rest = new S3Request('PUT', $bucket, '');
|
529 |
-
$rest->setParameter('logging', null);
|
530 |
-
$rest->data = $dom->saveXML();
|
531 |
-
$rest->size = strlen($rest->data);
|
532 |
-
$rest->setHeader('Content-Type', 'application/xml');
|
533 |
-
$rest = $rest->getResponse();
|
534 |
-
if ($rest->error === false && $rest->code !== 200)
|
535 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
536 |
-
if ($rest->error !== false) {
|
537 |
-
trigger_error(sprintf("S3::setBucketLogging({$bucket}, {$uri}): [%s] %s",
|
538 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
539 |
-
return false;
|
540 |
-
}
|
541 |
-
return true;
|
542 |
-
}
|
543 |
-
|
544 |
-
|
545 |
-
/**
|
546 |
-
* Get logging status for a bucket
|
547 |
-
*
|
548 |
-
* This will return false if logging is not enabled.
|
549 |
-
* Note: To enable logging, you also need to grant write access to the log group
|
550 |
-
*
|
551 |
-
* @param string $bucket Bucket name
|
552 |
-
* @return array | false
|
553 |
-
*/
|
554 |
-
public static function getBucketLogging($bucket) {
|
555 |
-
$rest = new S3Request('GET', $bucket, '');
|
556 |
-
$rest->setParameter('logging', null);
|
557 |
-
$rest = $rest->getResponse();
|
558 |
-
if ($rest->error === false && $rest->code !== 200)
|
559 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
560 |
-
if ($rest->error !== false) {
|
561 |
-
trigger_error(sprintf("S3::getBucketLogging({$bucket}): [%s] %s",
|
562 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
563 |
-
return false;
|
564 |
-
}
|
565 |
-
if (!isset($rest->body->LoggingEnabled)) return false; // No logging
|
566 |
-
return array(
|
567 |
-
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
|
568 |
-
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
|
569 |
-
);
|
570 |
-
}
|
571 |
-
|
572 |
-
|
573 |
-
/**
|
574 |
-
* Disable bucket logging
|
575 |
-
*
|
576 |
-
* @param string $bucket Bucket name
|
577 |
-
* @return boolean
|
578 |
-
*/
|
579 |
-
public static function disableBucketLogging($bucket) {
|
580 |
-
return self::setBucketLogging($bucket, null);
|
581 |
-
}
|
582 |
-
|
583 |
-
|
584 |
-
/**
|
585 |
-
* Get a bucket's location
|
586 |
-
*
|
587 |
-
* @param string $bucket Bucket name
|
588 |
-
* @return string | false
|
589 |
-
*/
|
590 |
-
public static function getBucketLocation($bucket) {
|
591 |
-
$rest = new S3Request('GET', $bucket, '');
|
592 |
-
$rest->setParameter('location', null);
|
593 |
-
$rest = $rest->getResponse();
|
594 |
-
if ($rest->error === false && $rest->code !== 200)
|
595 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
596 |
-
if ($rest->error !== false) {
|
597 |
-
trigger_error(sprintf("S3::getBucketLocation({$bucket}): [%s] %s",
|
598 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
599 |
-
return false;
|
600 |
-
}
|
601 |
-
return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
|
602 |
-
}
|
603 |
-
|
604 |
-
|
605 |
-
/**
|
606 |
-
* Set object or bucket Access Control Policy
|
607 |
-
*
|
608 |
-
* @param string $bucket Bucket name
|
609 |
-
* @param string $uri Object URI
|
610 |
-
* @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
|
611 |
-
* @return boolean
|
612 |
-
*/
|
613 |
-
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array()) {
|
614 |
-
$dom = new DOMDocument;
|
615 |
-
$dom->formatOutput = true;
|
616 |
-
$accessControlPolicy = $dom->createElement('AccessControlPolicy');
|
617 |
-
$accessControlList = $dom->createElement('AccessControlList');
|
618 |
-
|
619 |
-
// It seems the owner has to be passed along too
|
620 |
-
$owner = $dom->createElement('Owner');
|
621 |
-
$owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
|
622 |
-
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
|
623 |
-
$accessControlPolicy->appendChild($owner);
|
624 |
-
|
625 |
-
foreach ($acp['acl'] as $g) {
|
626 |
-
$grant = $dom->createElement('Grant');
|
627 |
-
$grantee = $dom->createElement('Grantee');
|
628 |
-
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
629 |
-
if (isset($g['id'])) { // CanonicalUser (DisplayName is omitted)
|
630 |
-
$grantee->setAttribute('xsi:type', 'CanonicalUser');
|
631 |
-
$grantee->appendChild($dom->createElement('ID', $g['id']));
|
632 |
-
} elseif (isset($g['email'])) { // AmazonCustomerByEmail
|
633 |
-
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
|
634 |
-
$grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
|
635 |
-
} elseif ($g['type'] == 'Group') { // Group
|
636 |
-
$grantee->setAttribute('xsi:type', 'Group');
|
637 |
-
$grantee->appendChild($dom->createElement('URI', $g['uri']));
|
638 |
-
}
|
639 |
-
$grant->appendChild($grantee);
|
640 |
-
$grant->appendChild($dom->createElement('Permission', $g['permission']));
|
641 |
-
$accessControlList->appendChild($grant);
|
642 |
-
}
|
643 |
-
|
644 |
-
$accessControlPolicy->appendChild($accessControlList);
|
645 |
-
$dom->appendChild($accessControlPolicy);
|
646 |
-
|
647 |
-
$rest = new S3Request('PUT', $bucket, $uri);
|
648 |
-
$rest->setParameter('acl', null);
|
649 |
-
$rest->data = $dom->saveXML();
|
650 |
-
$rest->size = strlen($rest->data);
|
651 |
-
$rest->setHeader('Content-Type', 'application/xml');
|
652 |
-
$rest = $rest->getResponse();
|
653 |
-
if ($rest->error === false && $rest->code !== 200)
|
654 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
655 |
-
if ($rest->error !== false) {
|
656 |
-
trigger_error(sprintf("S3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
657 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
658 |
-
return false;
|
659 |
-
}
|
660 |
-
return true;
|
661 |
-
}
|
662 |
-
|
663 |
-
|
664 |
-
/**
|
665 |
-
* Get object or bucket Access Control Policy
|
666 |
-
*
|
667 |
-
* @param string $bucket Bucket name
|
668 |
-
* @param string $uri Object URI
|
669 |
-
* @return mixed | false
|
670 |
-
*/
|
671 |
-
public static function getAccessControlPolicy($bucket, $uri = '') {
|
672 |
-
$rest = new S3Request('GET', $bucket, $uri);
|
673 |
-
$rest->setParameter('acl', null);
|
674 |
-
$rest = $rest->getResponse();
|
675 |
-
if ($rest->error === false && $rest->code !== 200)
|
676 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
677 |
-
if ($rest->error !== false) {
|
678 |
-
trigger_error(sprintf("S3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
679 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
680 |
-
return false;
|
681 |
-
}
|
682 |
-
|
683 |
-
$acp = array();
|
684 |
-
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) {
|
685 |
-
$acp['owner'] = array(
|
686 |
-
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
|
687 |
-
);
|
688 |
-
}
|
689 |
-
if (isset($rest->body->AccessControlList)) {
|
690 |
-
$acp['acl'] = array();
|
691 |
-
foreach ($rest->body->AccessControlList->Grant as $grant) {
|
692 |
-
foreach ($grant->Grantee as $grantee) {
|
693 |
-
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
|
694 |
-
$acp['acl'][] = array(
|
695 |
-
'type' => 'CanonicalUser',
|
696 |
-
'id' => (string)$grantee->ID,
|
697 |
-
'name' => (string)$grantee->DisplayName,
|
698 |
-
'permission' => (string)$grant->Permission
|
699 |
-
);
|
700 |
-
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
|
701 |
-
$acp['acl'][] = array(
|
702 |
-
'type' => 'AmazonCustomerByEmail',
|
703 |
-
'email' => (string)$grantee->EmailAddress,
|
704 |
-
'permission' => (string)$grant->Permission
|
705 |
-
);
|
706 |
-
elseif (isset($grantee->URI)) // Group
|
707 |
-
$acp['acl'][] = array(
|
708 |
-
'type' => 'Group',
|
709 |
-
'uri' => (string)$grantee->URI,
|
710 |
-
'permission' => (string)$grant->Permission
|
711 |
-
);
|
712 |
-
else continue;
|
713 |
-
}
|
714 |
-
}
|
715 |
-
}
|
716 |
-
return $acp;
|
717 |
-
}
|
718 |
-
|
719 |
-
|
720 |
-
/**
|
721 |
-
* Delete an object
|
722 |
-
*
|
723 |
-
* @param string $bucket Bucket name
|
724 |
-
* @param string $uri Object URI
|
725 |
-
* @return boolean
|
726 |
-
*/
|
727 |
-
public static function deleteObject($bucket, $uri) {
|
728 |
-
$rest = new S3Request('DELETE', $bucket, $uri);
|
729 |
-
$rest = $rest->getResponse();
|
730 |
-
if ($rest->error === false && $rest->code !== 204)
|
731 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
732 |
-
if ($rest->error !== false) {
|
733 |
-
trigger_error(sprintf("S3::deleteObject(): [%s] %s",
|
734 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
735 |
-
return false;
|
736 |
-
}
|
737 |
-
return true;
|
738 |
-
}
|
739 |
-
|
740 |
-
|
741 |
-
/**
|
742 |
-
* Get a query string authenticated URL
|
743 |
-
*
|
744 |
-
* @param string $bucket Bucket name
|
745 |
-
* @param string $uri Object URI
|
746 |
-
* @param integer $lifetime Lifetime in seconds
|
747 |
-
* @param boolean $hostBucket Use the bucket name as the hostname
|
748 |
-
* @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
|
749 |
-
* @return string
|
750 |
-
*/
|
751 |
-
public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false) {
|
752 |
-
$expires = time() + $lifetime;
|
753 |
-
$uri = str_replace('%2F', '/', rawurlencode($uri)); // URI should be encoded (thanks Sean O'Dea)
|
754 |
-
return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
|
755 |
-
$hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
|
756 |
-
urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
|
757 |
-
}
|
758 |
-
|
759 |
-
/**
|
760 |
-
* Get upload POST parameters for form uploads
|
761 |
-
*
|
762 |
-
* @param string $bucket Bucket name
|
763 |
-
* @param string $uriPrefix Object URI prefix
|
764 |
-
* @param constant $acl ACL constant
|
765 |
-
* @param integer $lifetime Lifetime in seconds
|
766 |
-
* @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
|
767 |
-
* @param string $successRedirect Redirect URL or 200 / 201 status code
|
768 |
-
* @param array $amzHeaders Array of x-amz-meta-* headers
|
769 |
-
* @param array $headers Array of request headers or content type as a string
|
770 |
-
* @param boolean $flashVars Includes additional "Filename" variable posted by Flash
|
771 |
-
* @return object
|
772 |
-
*/
|
773 |
-
public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600, $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false) {
|
774 |
-
// Create policy object
|
775 |
-
$policy = new stdClass;
|
776 |
-
$policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
|
777 |
-
$policy->conditions = array();
|
778 |
-
$obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
|
779 |
-
$obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
|
780 |
-
|
781 |
-
$obj = new stdClass; // 200 for non-redirect uploads
|
782 |
-
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
783 |
-
$obj->success_action_status = (string)$successRedirect;
|
784 |
-
else // URL
|
785 |
-
$obj->success_action_redirect = $successRedirect;
|
786 |
-
array_push($policy->conditions, $obj);
|
787 |
-
|
788 |
-
array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
|
789 |
-
if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
|
790 |
-
foreach (array_keys($headers) as $headerKey)
|
791 |
-
array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
|
792 |
-
foreach ($amzHeaders as $headerKey => $headerVal) {
|
793 |
-
$obj = new stdClass; $obj->{$headerKey} = (string)$headerVal; array_push($policy->conditions, $obj);
|
794 |
-
}
|
795 |
-
array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
|
796 |
-
$policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
|
797 |
-
|
798 |
-
// Create parameters
|
799 |
-
$params = new stdClass;
|
800 |
-
$params->AWSAccessKeyId = self::$__accessKey;
|
801 |
-
$params->key = $uriPrefix.'${filename}';
|
802 |
-
$params->acl = $acl;
|
803 |
-
$params->policy = $policy; unset($policy);
|
804 |
-
$params->signature = self::__getHash($params->policy);
|
805 |
-
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
806 |
-
$params->success_action_status = (string)$successRedirect;
|
807 |
-
else
|
808 |
-
$params->success_action_redirect = $successRedirect;
|
809 |
-
foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
810 |
-
foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
811 |
-
return $params;
|
812 |
-
}
|
813 |
-
|
814 |
-
/**
|
815 |
-
* Create a CloudFront distribution
|
816 |
-
*
|
817 |
-
* @param string $bucket Bucket name
|
818 |
-
* @param boolean $enabled Enabled (true/false)
|
819 |
-
* @param array $cnames Array containing CNAME aliases
|
820 |
-
* @param string $comment Use the bucket name as the hostname
|
821 |
-
* @return array | false
|
822 |
-
*/
|
823 |
-
public static function createDistribution($bucket, $enabled = true, $cnames = array(), $comment = '') {
|
824 |
-
self::$useSSL = true; // CloudFront requires SSL
|
825 |
-
$rest = new S3Request('POST', '', '2008-06-30/distribution', 'cloudfront.amazonaws.com');
|
826 |
-
$rest->data = self::__getCloudFrontDistributionConfigXML($bucket.'.s3.amazonaws.com', $enabled, $comment, (string)microtime(true), $cnames);
|
827 |
-
$rest->size = strlen($rest->data);
|
828 |
-
$rest->setHeader('Content-Type', 'application/xml');
|
829 |
-
$rest = self::__getCloudFrontResponse($rest);
|
830 |
-
|
831 |
-
if ($rest->error === false && $rest->code !== 201)
|
832 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
833 |
-
if ($rest->error !== false) {
|
834 |
-
trigger_error(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", '$comment'): [%s] %s",
|
835 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
836 |
-
return false;
|
837 |
-
} elseif ($rest->body instanceof SimpleXMLElement)
|
838 |
-
return self::__parseCloudFrontDistributionConfig($rest->body);
|
839 |
-
return false;
|
840 |
-
}
|
841 |
-
|
842 |
-
|
843 |
-
/**
|
844 |
-
* Get CloudFront distribution info
|
845 |
-
*
|
846 |
-
* @param string $distributionId Distribution ID from listDistributions()
|
847 |
-
* @return array | false
|
848 |
-
*/
|
849 |
-
public static function getDistribution($distributionId) {
|
850 |
-
self::$useSSL = true; // CloudFront requires SSL
|
851 |
-
$rest = new S3Request('GET', '', '2008-06-30/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
|
852 |
-
$rest = self::__getCloudFrontResponse($rest);
|
853 |
-
|
854 |
-
if ($rest->error === false && $rest->code !== 200)
|
855 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
856 |
-
if ($rest->error !== false) {
|
857 |
-
trigger_error(sprintf("S3::getDistribution($distributionId): [%s] %s",
|
858 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
859 |
-
return false;
|
860 |
-
} elseif ($rest->body instanceof SimpleXMLElement) {
|
861 |
-
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
862 |
-
$dist['hash'] = $rest->headers['hash'];
|
863 |
-
return $dist;
|
864 |
-
}
|
865 |
-
return false;
|
866 |
-
}
|
867 |
-
|
868 |
-
|
869 |
-
/**
|
870 |
-
* Update a CloudFront distribution
|
871 |
-
*
|
872 |
-
* @param array $dist Distribution array info identical to output of getDistribution()
|
873 |
-
* @return array | false
|
874 |
-
*/
|
875 |
-
public static function updateDistribution($dist) {
|
876 |
-
self::$useSSL = true; // CloudFront requires SSL
|
877 |
-
$rest = new S3Request('PUT', '', '2008-06-30/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
|
878 |
-
$rest->data = self::__getCloudFrontDistributionConfigXML($dist['origin'], $dist['enabled'], $dist['comment'], $dist['callerReference'], $dist['cnames']);
|
879 |
-
$rest->size = strlen($rest->data);
|
880 |
-
$rest->setHeader('If-Match', $dist['hash']);
|
881 |
-
$rest = self::__getCloudFrontResponse($rest);
|
882 |
-
|
883 |
-
if ($rest->error === false && $rest->code !== 200)
|
884 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
885 |
-
if ($rest->error !== false) {
|
886 |
-
trigger_error(sprintf("S3::updateDistribution({$dist['id']}, ".(int)$enabled.", '$comment'): [%s] %s",
|
887 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
888 |
-
return false;
|
889 |
-
} else {
|
890 |
-
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
891 |
-
$dist['hash'] = $rest->headers['hash'];
|
892 |
-
return $dist;
|
893 |
-
}
|
894 |
-
return false;
|
895 |
-
}
|
896 |
-
|
897 |
-
|
898 |
-
/**
|
899 |
-
* Delete a CloudFront distribution
|
900 |
-
*
|
901 |
-
* @param array $dist Distribution array info identical to output of getDistribution()
|
902 |
-
* @return boolean
|
903 |
-
*/
|
904 |
-
public static function deleteDistribution($dist) {
|
905 |
-
self::$useSSL = true; // CloudFront requires SSL
|
906 |
-
$rest = new S3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
|
907 |
-
$rest->setHeader('If-Match', $dist['hash']);
|
908 |
-
$rest = self::__getCloudFrontResponse($rest);
|
909 |
-
|
910 |
-
if ($rest->error === false && $rest->code !== 204)
|
911 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
912 |
-
if ($rest->error !== false) {
|
913 |
-
trigger_error(sprintf("S3::deleteDistribution({$dist['id']}): [%s] %s",
|
914 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
915 |
-
return false;
|
916 |
-
}
|
917 |
-
return true;
|
918 |
-
}
|
919 |
-
|
920 |
-
|
921 |
-
/**
|
922 |
-
* Get a list of CloudFront distributions
|
923 |
-
*
|
924 |
-
* @return array
|
925 |
-
*/
|
926 |
-
public static function listDistributions() {
|
927 |
-
self::$useSSL = true; // CloudFront requires SSL
|
928 |
-
$rest = new S3Request('GET', '', '2008-06-30/distribution', 'cloudfront.amazonaws.com');
|
929 |
-
$rest = self::__getCloudFrontResponse($rest);
|
930 |
-
|
931 |
-
if ($rest->error === false && $rest->code !== 200)
|
932 |
-
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
933 |
-
if ($rest->error !== false) {
|
934 |
-
trigger_error(sprintf("S3::listDistributions(): [%s] %s",
|
935 |
-
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
936 |
-
return false;
|
937 |
-
} elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary)) {
|
938 |
-
$list = array();
|
939 |
-
if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated)) {
|
940 |
-
//$info['marker'] = (string)$rest->body->Marker;
|
941 |
-
//$info['maxItems'] = (int)$rest->body->MaxItems;
|
942 |
-
//$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
|
943 |
-
}
|
944 |
-
foreach ($rest->body->DistributionSummary as $summary) {
|
945 |
-
$list[(string)$summary->Id] = self::__parseCloudFrontDistributionConfig($summary);
|
946 |
-
}
|
947 |
-
return $list;
|
948 |
-
}
|
949 |
-
return array();
|
950 |
-
}
|
951 |
-
|
952 |
-
|
953 |
-
/**
|
954 |
-
* Get a DistributionConfig DOMDocument
|
955 |
-
*
|
956 |
-
* @internal Used to create XML in createDistribution() and updateDistribution()
|
957 |
-
* @param string $bucket Origin bucket
|
958 |
-
* @param boolean $enabled Enabled (true/false)
|
959 |
-
* @param string $comment Comment to append
|
960 |
-
* @param string $callerReference Caller reference
|
961 |
-
* @param array $cnames Array of CNAME aliases
|
962 |
-
* @return string
|
963 |
-
*/
|
964 |
-
private static function __getCloudFrontDistributionConfigXML($bucket, $enabled, $comment, $callerReference = '0', $cnames = array()) {
|
965 |
-
$dom = new DOMDocument('1.0', 'UTF-8');
|
966 |
-
$dom->formatOutput = true;
|
967 |
-
$distributionConfig = $dom->createElement('DistributionConfig');
|
968 |
-
$distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2008-06-30/');
|
969 |
-
$distributionConfig->appendChild($dom->createElement('Origin', $bucket));
|
970 |
-
$distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
|
971 |
-
foreach ($cnames as $cname)
|
972 |
-
$distributionConfig->appendChild($dom->createElement('CNAME', $cname));
|
973 |
-
if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
|
974 |
-
$distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
|
975 |
-
$dom->appendChild($distributionConfig);
|
976 |
-
return $dom->saveXML();
|
977 |
-
}
|
978 |
-
|
979 |
-
|
980 |
-
/**
|
981 |
-
* Parse a CloudFront distribution config
|
982 |
-
*
|
983 |
-
* @internal Used to parse the CloudFront DistributionConfig node to an array
|
984 |
-
* @param object &$node DOMNode
|
985 |
-
* @return array
|
986 |
-
*/
|
987 |
-
private static function __parseCloudFrontDistributionConfig(&$node) {
|
988 |
-
$dist = array();
|
989 |
-
if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName)) {
|
990 |
-
$dist['id'] = (string)$node->Id;
|
991 |
-
$dist['status'] = (string)$node->Status;
|
992 |
-
$dist['time'] = strtotime((string)$node->LastModifiedTime);
|
993 |
-
$dist['domain'] = (string)$node->DomainName;
|
994 |
-
}
|
995 |
-
if (isset($node->CallerReference))
|
996 |
-
$dist['callerReference'] = (string)$node->CallerReference;
|
997 |
-
if (isset($node->Comment))
|
998 |
-
$dist['comment'] = (string)$node->Comment;
|
999 |
-
if (isset($node->Enabled, $node->Origin)) {
|
1000 |
-
$dist['origin'] = (string)$node->Origin;
|
1001 |
-
$dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
|
1002 |
-
} elseif (isset($node->DistributionConfig)) {
|
1003 |
-
$dist = array_merge($dist, self::__parseCloudFrontDistributionConfig($node->DistributionConfig));
|
1004 |
-
}
|
1005 |
-
if (isset($node->CNAME)) {
|
1006 |
-
$dist['cnames'] = array();
|
1007 |
-
foreach ($node->CNAME as $cname) $dist['cnames'][(string)$cname] = (string)$cname;
|
1008 |
-
}
|
1009 |
-
return $dist;
|
1010 |
-
}
|
1011 |
-
|
1012 |
-
|
1013 |
-
/**
|
1014 |
-
* Grab CloudFront response
|
1015 |
-
*
|
1016 |
-
* @internal Used to parse the CloudFront S3Request::getResponse() output
|
1017 |
-
* @param object &$rest S3Request instance
|
1018 |
-
* @return object
|
1019 |
-
*/
|
1020 |
-
private static function __getCloudFrontResponse(&$rest) {
|
1021 |
-
$rest->getResponse();
|
1022 |
-
if ($rest->response->error === false && isset($rest->response->body) &&
|
1023 |
-
is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml') {
|
1024 |
-
$rest->response->body = simplexml_load_string($rest->response->body);
|
1025 |
-
// Grab CloudFront errors
|
1026 |
-
if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
|
1027 |
-
$rest->response->body->Error->Message)) {
|
1028 |
-
$rest->response->error = array(
|
1029 |
-
'code' => (string)$rest->response->body->Error->Code,
|
1030 |
-
'message' => (string)$rest->response->body->Error->Message
|
1031 |
-
);
|
1032 |
-
unset($rest->response->body);
|
1033 |
-
}
|
1034 |
-
}
|
1035 |
-
return $rest->response;
|
1036 |
-
}
|
1037 |
-
|
1038 |
-
|
1039 |
-
/**
|
1040 |
-
* Get MIME type for file
|
1041 |
-
*
|
1042 |
-
* @internal Used to get mime types
|
1043 |
-
* @param string &$file File path
|
1044 |
-
* @return string
|
1045 |
-
*/
|
1046 |
-
public static function __getMimeType(&$file) {
|
1047 |
-
$type = false;
|
1048 |
-
// Fileinfo documentation says fileinfo_open() will use the
|
1049 |
-
// MAGIC env var for the magic file
|
1050 |
-
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
|
1051 |
-
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) {
|
1052 |
-
if (($type = finfo_file($finfo, $file)) !== false) {
|
1053 |
-
// Remove the charset and grab the last content-type
|
1054 |
-
$type = explode(' ', str_replace('; charset=', ';charset=', $type));
|
1055 |
-
$type = array_pop($type);
|
1056 |
-
$type = explode(';', $type);
|
1057 |
-
$type = trim(array_shift($type));
|
1058 |
-
}
|
1059 |
-
finfo_close($finfo);
|
1060 |
-
|
1061 |
-
// If anyone is still using mime_content_type()
|
1062 |
-
} elseif (function_exists('mime_content_type'))
|
1063 |
-
$type = trim(mime_content_type($file));
|
1064 |
-
|
1065 |
-
if ($type !== false && strlen($type) > 0) return $type;
|
1066 |
-
|
1067 |
-
// Otherwise do it the old fashioned way
|
1068 |
-
static $exts = array(
|
1069 |
-
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
|
1070 |
-
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
|
1071 |
-
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
|
1072 |
-
'zip' => 'application/zip', 'gz' => 'application/x-gzip',
|
1073 |
-
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
|
1074 |
-
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
|
1075 |
-
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
|
1076 |
-
'css' => 'text/css', 'js' => 'text/javascript',
|
1077 |
-
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
|
1078 |
-
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
|
1079 |
-
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
|
1080 |
-
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
|
1081 |
-
);
|
1082 |
-
$ext = strtolower(pathInfo($file, PATHINFO_EXTENSION));
|
1083 |
-
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
|
1084 |
-
}
|
1085 |
-
|
1086 |
-
|
1087 |
-
/**
|
1088 |
-
* Generate the auth string: "AWS AccessKey:Signature"
|
1089 |
-
*
|
1090 |
-
* @internal Used by S3Request::getResponse()
|
1091 |
-
* @param string $string String to sign
|
1092 |
-
* @return string
|
1093 |
-
*/
|
1094 |
-
public static function __getSignature($string) {
|
1095 |
-
return 'AWS '.self::$__accessKey.':'.self::__getHash($string);
|
1096 |
-
}
|
1097 |
-
|
1098 |
-
|
1099 |
-
/**
|
1100 |
-
* Creates a HMAC-SHA1 hash
|
1101 |
-
*
|
1102 |
-
* This uses the hash extension if loaded
|
1103 |
-
*
|
1104 |
-
* @internal Used by __getSignature()
|
1105 |
-
* @param string $string String to sign
|
1106 |
-
* @return string
|
1107 |
-
*/
|
1108 |
-
private static function __getHash($string) {
|
1109 |
-
return base64_encode(extension_loaded('hash') ?
|
1110 |
-
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
|
1111 |
-
(str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
|
1112 |
-
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
|
1113 |
-
(str_repeat(chr(0x36), 64))) . $string)))));
|
1114 |
-
}
|
1115 |
-
|
1116 |
-
}
|
1117 |
-
|
1118 |
-
final class S3Request {
|
1119 |
-
private $verb, $bucket, $uri, $resource = '', $parameters = array(),
|
1120 |
-
$amzHeaders = array(), $headers = array(
|
1121 |
-
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
|
1122 |
-
);
|
1123 |
-
public $fp = false, $size = 0, $data = false, $response;
|
1124 |
-
|
1125 |
-
|
1126 |
-
/**
|
1127 |
-
* Constructor
|
1128 |
-
*
|
1129 |
-
* @param string $verb Verb
|
1130 |
-
* @param string $bucket Bucket name
|
1131 |
-
* @param string $uri Object URI
|
1132 |
-
* @return mixed
|
1133 |
-
*/
|
1134 |
-
function __construct($verb, $bucket = '', $uri = '', $defaultHost = 's3.amazonaws.com') {
|
1135 |
-
$this->verb = $verb;
|
1136 |
-
$this->bucket = strtolower($bucket);
|
1137 |
-
$this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
|
1138 |
-
|
1139 |
-
if ($this->bucket !== '') {
|
1140 |
-
$this->headers['Host'] = $this->bucket.'.'.$defaultHost;
|
1141 |
-
$this->resource = '/'.$this->bucket.$this->uri;
|
1142 |
-
} else {
|
1143 |
-
$this->headers['Host'] = $defaultHost;
|
1144 |
-
//$this->resource = strlen($this->uri) > 1 ? '/'.$this->bucket.$this->uri : $this->uri;
|
1145 |
-
$this->resource = $this->uri;
|
1146 |
-
}
|
1147 |
-
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
|
1148 |
-
|
1149 |
-
$this->response = new STDClass;
|
1150 |
-
$this->response->error = false;
|
1151 |
-
}
|
1152 |
-
|
1153 |
-
|
1154 |
-
/**
|
1155 |
-
* Set request parameter
|
1156 |
-
*
|
1157 |
-
* @param string $key Key
|
1158 |
-
* @param string $value Value
|
1159 |
-
* @return void
|
1160 |
-
*/
|
1161 |
-
public function setParameter($key, $value) {
|
1162 |
-
$this->parameters[$key] = $value;
|
1163 |
-
}
|
1164 |
-
|
1165 |
-
|
1166 |
-
/**
|
1167 |
-
* Set request header
|
1168 |
-
*
|
1169 |
-
* @param string $key Key
|
1170 |
-
* @param string $value Value
|
1171 |
-
* @return void
|
1172 |
-
*/
|
1173 |
-
public function setHeader($key, $value) {
|
1174 |
-
$this->headers[$key] = $value;
|
1175 |
-
}
|
1176 |
-
|
1177 |
-
|
1178 |
-
/**
|
1179 |
-
* Set x-amz-meta-* header
|
1180 |
-
*
|
1181 |
-
* @param string $key Key
|
1182 |
-
* @param string $value Value
|
1183 |
-
* @return void
|
1184 |
-
*/
|
1185 |
-
public function setAmzHeader($key, $value) {
|
1186 |
-
$this->amzHeaders[$key] = $value;
|
1187 |
-
}
|
1188 |
-
|
1189 |
-
|
1190 |
-
/**
|
1191 |
-
* Get the S3 response
|
1192 |
-
*
|
1193 |
-
* @return object | false
|
1194 |
-
*/
|
1195 |
-
public function getResponse() {
|
1196 |
-
$query = '';
|
1197 |
-
if (sizeof($this->parameters) > 0) {
|
1198 |
-
$query = substr($this->uri, -1) !== '?' ? '?' : '&';
|
1199 |
-
foreach ($this->parameters as $var => $value)
|
1200 |
-
if ($value == null || $value == '') $query .= $var.'&';
|
1201 |
-
// Parameters should be encoded (thanks Sean O'Dea)
|
1202 |
-
else $query .= $var.'='.rawurlencode($value).'&';
|
1203 |
-
$query = substr($query, 0, -1);
|
1204 |
-
$this->uri .= $query;
|
1205 |
-
|
1206 |
-
if (array_key_exists('acl', $this->parameters) ||
|
1207 |
-
array_key_exists('location', $this->parameters) ||
|
1208 |
-
array_key_exists('torrent', $this->parameters) ||
|
1209 |
-
array_key_exists('logging', $this->parameters))
|
1210 |
-
$this->resource .= $query;
|
1211 |
-
}
|
1212 |
-
$url = ((S3::$useSSL && extension_loaded('openssl')) ?
|
1213 |
-
'https://':'http://').$this->headers['Host'].$this->uri;
|
1214 |
-
//var_dump($this->bucket, $this->uri, $this->resource, $url);
|
1215 |
-
|
1216 |
-
// Basic setup
|
1217 |
-
$curl = curl_init();
|
1218 |
-
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
|
1219 |
-
|
1220 |
-
if (S3::$useSSL) {
|
1221 |
-
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
|
1222 |
-
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
|
1223 |
-
}
|
1224 |
-
|
1225 |
-
curl_setopt($curl, CURLOPT_URL, $url);
|
1226 |
-
|
1227 |
-
// Headers
|
1228 |
-
$headers = array(); $amz = array();
|
1229 |
-
foreach ($this->amzHeaders as $header => $value)
|
1230 |
-
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1231 |
-
foreach ($this->headers as $header => $value)
|
1232 |
-
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1233 |
-
|
1234 |
-
// Collect AMZ headers for signature
|
1235 |
-
foreach ($this->amzHeaders as $header => $value)
|
1236 |
-
if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
|
1237 |
-
|
1238 |
-
// AMZ headers must be sorted
|
1239 |
-
if (sizeof($amz) > 0) {
|
1240 |
-
sort($amz);
|
1241 |
-
$amz = "\n".implode("\n", $amz);
|
1242 |
-
} else $amz = '';
|
1243 |
-
|
1244 |
-
// Authorization string (CloudFront stringToSign should only contain a date)
|
1245 |
-
$headers[] = 'Authorization: ' . S3::__getSignature(
|
1246 |
-
$this->headers['Host'] == 'cloudfront.amazonaws.com' ? $this->headers['Date'] :
|
1247 |
-
$this->verb."\n".$this->headers['Content-MD5']."\n".
|
1248 |
-
$this->headers['Content-Type']."\n".$this->headers['Date'].$amz."\n".$this->resource
|
1249 |
-
);
|
1250 |
-
|
1251 |
-
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
1252 |
-
curl_setopt($curl, CURLOPT_HEADER, false);
|
1253 |
-
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
|
1254 |
-
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
|
1255 |
-
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
|
1256 |
-
//curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
1257 |
-
|
1258 |
-
// Request types
|
1259 |
-
switch ($this->verb) {
|
1260 |
-
case 'GET': break;
|
1261 |
-
case 'PUT': case 'POST': // POST only used for CloudFront
|
1262 |
-
if ($this->fp !== false) {
|
1263 |
-
curl_setopt($curl, CURLOPT_PUT, true);
|
1264 |
-
curl_setopt($curl, CURLOPT_INFILE, $this->fp);
|
1265 |
-
if ($this->size >= 0)
|
1266 |
-
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
|
1267 |
-
} elseif ($this->data !== false) {
|
1268 |
-
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1269 |
-
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
|
1270 |
-
if ($this->size >= 0)
|
1271 |
-
curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size);
|
1272 |
-
} else
|
1273 |
-
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1274 |
-
break;
|
1275 |
-
case 'HEAD':
|
1276 |
-
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
|
1277 |
-
curl_setopt($curl, CURLOPT_NOBODY, true);
|
1278 |
-
break;
|
1279 |
-
case 'DELETE':
|
1280 |
-
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
1281 |
-
break;
|
1282 |
-
default: break;
|
1283 |
-
}
|
1284 |
-
|
1285 |
-
// Execute, grab errors
|
1286 |
-
if (curl_exec($curl))
|
1287 |
-
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
1288 |
-
else
|
1289 |
-
$this->response->error = array(
|
1290 |
-
'code' => curl_errno($curl),
|
1291 |
-
'message' => curl_error($curl),
|
1292 |
-
'resource' => $this->resource
|
1293 |
-
);
|
1294 |
-
|
1295 |
-
@curl_close($curl);
|
1296 |
-
|
1297 |
-
// Parse body into XML
|
1298 |
-
if ($this->response->error === false && isset($this->response->headers['type']) &&
|
1299 |
-
$this->response->headers['type'] == 'application/xml' && isset($this->response->body)) {
|
1300 |
-
$this->response->body = simplexml_load_string($this->response->body);
|
1301 |
-
|
1302 |
-
// Grab S3 errors
|
1303 |
-
if (!in_array($this->response->code, array(200, 204)) &&
|
1304 |
-
isset($this->response->body->Code, $this->response->body->Message)) {
|
1305 |
-
$this->response->error = array(
|
1306 |
-
'code' => (string)$this->response->body->Code,
|
1307 |
-
'message' => (string)$this->response->body->Message
|
1308 |
-
);
|
1309 |
-
if (isset($this->response->body->Resource))
|
1310 |
-
$this->response->error['resource'] = (string)$this->response->body->Resource;
|
1311 |
-
unset($this->response->body);
|
1312 |
-
}
|
1313 |
-
}
|
1314 |
-
|
1315 |
-
// Clean up file resources
|
1316 |
-
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
|
1317 |
-
|
1318 |
-
return $this->response;
|
1319 |
-
}
|
1320 |
-
|
1321 |
-
|
1322 |
-
/**
|
1323 |
-
* CURL write callback
|
1324 |
-
*
|
1325 |
-
* @param resource &$curl CURL resource
|
1326 |
-
* @param string &$data Data
|
1327 |
-
* @return integer
|
1328 |
-
*/
|
1329 |
-
private function __responseWriteCallback(&$curl, &$data) {
|
1330 |
-
if ($this->response->code == 200 && $this->fp !== false)
|
1331 |
-
return fwrite($this->fp, $data);
|
1332 |
-
else
|
1333 |
-
$this->response->body .= $data;
|
1334 |
-
return strlen($data);
|
1335 |
-
}
|
1336 |
-
|
1337 |
-
|
1338 |
-
/**
|
1339 |
-
* CURL header callback
|
1340 |
-
*
|
1341 |
-
* @param resource &$curl CURL resource
|
1342 |
-
* @param string &$data Data
|
1343 |
-
* @return integer
|
1344 |
-
*/
|
1345 |
-
private function __responseHeaderCallback(&$curl, &$data) {
|
1346 |
-
if (($strlen = strlen($data)) <= 2) return $strlen;
|
1347 |
-
if (substr($data, 0, 4) == 'HTTP')
|
1348 |
-
$this->response->code = (int)substr($data, 9, 3);
|
1349 |
-
else {
|
1350 |
-
list($header, $value) = explode(': ', trim($data), 2);
|
1351 |
-
if ($header == 'Last-Modified')
|
1352 |
-
$this->response->headers['time'] = strtotime($value);
|
1353 |
-
elseif ($header == 'Content-Length')
|
1354 |
-
$this->response->headers['size'] = (int)$value;
|
1355 |
-
elseif ($header == 'Content-Type')
|
1356 |
-
$this->response->headers['type'] = $value;
|
1357 |
-
elseif ($header == 'ETag')
|
1358 |
-
$this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
|
1359 |
-
elseif (preg_match('/^x-amz-meta-.*$/', $header))
|
1360 |
-
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
|
1361 |
-
}
|
1362 |
-
return $strlen;
|
1363 |
-
}
|
1364 |
-
|
1365 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* $Id: S3.php 47 2009-07-20 01:25:40Z don.schonknecht $
|
4 |
+
*
|
5 |
+
* Copyright (c) 2008, 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.4.0
|
36 |
+
*/
|
37 |
+
class S3 {
|
38 |
+
// ACL flags
|
39 |
+
const ACL_PRIVATE = 'private';
|
40 |
+
const ACL_PUBLIC_READ = 'public-read';
|
41 |
+
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
|
42 |
+
const ACL_AUTHENTICATED_READ = 'authenticated-read';
|
43 |
+
|
44 |
+
public static $useSSL = true;
|
45 |
+
|
46 |
+
private static $__accessKey; // AWS Access key
|
47 |
+
private static $__secretKey; // AWS Secret key
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Constructor - if you're not using the class statically
|
52 |
+
*
|
53 |
+
* @param string $accessKey Access key
|
54 |
+
* @param string $secretKey Secret key
|
55 |
+
* @param boolean $useSSL Enable SSL
|
56 |
+
* @return void
|
57 |
+
*/
|
58 |
+
public function __construct($accessKey = null, $secretKey = null, $useSSL = true) {
|
59 |
+
if ($accessKey !== null && $secretKey !== null)
|
60 |
+
self::setAuth($accessKey, $secretKey);
|
61 |
+
self::$useSSL = $useSSL;
|
62 |
+
}
|
63 |
+
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set AWS access key and secret key
|
67 |
+
*
|
68 |
+
* @param string $accessKey Access key
|
69 |
+
* @param string $secretKey Secret key
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
+
public static function setAuth($accessKey, $secretKey) {
|
73 |
+
self::$__accessKey = $accessKey;
|
74 |
+
self::$__secretKey = $secretKey;
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get a list of buckets
|
80 |
+
*
|
81 |
+
* @param boolean $detailed Returns detailed bucket list when true
|
82 |
+
* @return array | false
|
83 |
+
*/
|
84 |
+
public static function listBuckets($detailed = false) {
|
85 |
+
$rest = new S3Request('GET', '', '');
|
86 |
+
$rest = $rest->getResponse();
|
87 |
+
if ($rest->error === false && $rest->code !== 200)
|
88 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
89 |
+
if ($rest->error !== false) {
|
90 |
+
trigger_error(sprintf("S3::listBuckets(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
91 |
+
return false;
|
92 |
+
}
|
93 |
+
$results = array();
|
94 |
+
if (!isset($rest->body->Buckets)) return $results;
|
95 |
+
|
96 |
+
if ($detailed) {
|
97 |
+
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
|
98 |
+
$results['owner'] = array(
|
99 |
+
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
|
100 |
+
);
|
101 |
+
$results['buckets'] = array();
|
102 |
+
foreach ($rest->body->Buckets->Bucket as $b)
|
103 |
+
$results['buckets'][] = array(
|
104 |
+
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
|
105 |
+
);
|
106 |
+
} else
|
107 |
+
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
|
108 |
+
|
109 |
+
return $results;
|
110 |
+
}
|
111 |
+
|
112 |
+
|
113 |
+
/*
|
114 |
+
* Get contents for a bucket
|
115 |
+
*
|
116 |
+
* If maxKeys is null this method will loop through truncated result sets
|
117 |
+
*
|
118 |
+
* @param string $bucket Bucket name
|
119 |
+
* @param string $prefix Prefix
|
120 |
+
* @param string $marker Marker (last file listed)
|
121 |
+
* @param string $maxKeys Max keys (maximum number of keys to return)
|
122 |
+
* @param string $delimiter Delimiter
|
123 |
+
* @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
|
124 |
+
* @return array | false
|
125 |
+
*/
|
126 |
+
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false) {
|
127 |
+
$rest = new S3Request('GET', $bucket, '');
|
128 |
+
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
129 |
+
if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
|
130 |
+
if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
|
131 |
+
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
132 |
+
$response = $rest->getResponse();
|
133 |
+
if ($response->error === false && $response->code !== 200)
|
134 |
+
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
|
135 |
+
if ($response->error !== false) {
|
136 |
+
trigger_error(sprintf("S3::getBucket(): [%s] %s", $response->error['code'], $response->error['message']), E_USER_WARNING);
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
|
140 |
+
$results = array();
|
141 |
+
|
142 |
+
$nextMarker = null;
|
143 |
+
if (isset($response->body, $response->body->Contents))
|
144 |
+
foreach ($response->body->Contents as $c) {
|
145 |
+
$results[(string)$c->Key] = array(
|
146 |
+
'name' => (string)$c->Key,
|
147 |
+
'time' => strtotime((string)$c->LastModified),
|
148 |
+
'size' => (int)$c->Size,
|
149 |
+
'hash' => substr((string)$c->ETag, 1, -1)
|
150 |
+
);
|
151 |
+
$nextMarker = (string)$c->Key;
|
152 |
+
}
|
153 |
+
|
154 |
+
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
155 |
+
foreach ($response->body->CommonPrefixes as $c)
|
156 |
+
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
157 |
+
|
158 |
+
if (isset($response->body, $response->body->IsTruncated) &&
|
159 |
+
(string)$response->body->IsTruncated == 'false') return $results;
|
160 |
+
|
161 |
+
if (isset($response->body, $response->body->NextMarker))
|
162 |
+
$nextMarker = (string)$response->body->NextMarker;
|
163 |
+
|
164 |
+
// Loop through truncated results if maxKeys isn't specified
|
165 |
+
if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
|
166 |
+
do {
|
167 |
+
$rest = new S3Request('GET', $bucket, '');
|
168 |
+
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
|
169 |
+
$rest->setParameter('marker', $nextMarker);
|
170 |
+
if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
|
171 |
+
|
172 |
+
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
|
173 |
+
|
174 |
+
if (isset($response->body, $response->body->Contents))
|
175 |
+
foreach ($response->body->Contents as $c) {
|
176 |
+
$results[(string)$c->Key] = array(
|
177 |
+
'name' => (string)$c->Key,
|
178 |
+
'time' => strtotime((string)$c->LastModified),
|
179 |
+
'size' => (int)$c->Size,
|
180 |
+
'hash' => substr((string)$c->ETag, 1, -1)
|
181 |
+
);
|
182 |
+
$nextMarker = (string)$c->Key;
|
183 |
+
}
|
184 |
+
|
185 |
+
if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
|
186 |
+
foreach ($response->body->CommonPrefixes as $c)
|
187 |
+
$results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
|
188 |
+
|
189 |
+
if (isset($response->body, $response->body->NextMarker))
|
190 |
+
$nextMarker = (string)$response->body->NextMarker;
|
191 |
+
|
192 |
+
} while ($response !== false && (string)$response->body->IsTruncated == 'true');
|
193 |
+
|
194 |
+
return $results;
|
195 |
+
}
|
196 |
+
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Put a bucket
|
200 |
+
*
|
201 |
+
* @param string $bucket Bucket name
|
202 |
+
* @param constant $acl ACL flag
|
203 |
+
* @param string $location Set as "EU" to create buckets hosted in Europe
|
204 |
+
* @return boolean
|
205 |
+
*/
|
206 |
+
public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false) {
|
207 |
+
$rest = new S3Request('PUT', $bucket, '');
|
208 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
209 |
+
|
210 |
+
if ($location !== false) {
|
211 |
+
$dom = new DOMDocument;
|
212 |
+
$createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
|
213 |
+
$locationConstraint = $dom->createElement('LocationConstraint', strtoupper($location));
|
214 |
+
$createBucketConfiguration->appendChild($locationConstraint);
|
215 |
+
$dom->appendChild($createBucketConfiguration);
|
216 |
+
$rest->data = $dom->saveXML();
|
217 |
+
$rest->size = strlen($rest->data);
|
218 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
219 |
+
}
|
220 |
+
$rest = $rest->getResponse();
|
221 |
+
|
222 |
+
if ($rest->error === false && $rest->code !== 200)
|
223 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
224 |
+
if ($rest->error !== false) {
|
225 |
+
trigger_error(sprintf("S3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
|
226 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
227 |
+
return false;
|
228 |
+
}
|
229 |
+
return true;
|
230 |
+
}
|
231 |
+
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Delete an empty bucket
|
235 |
+
*
|
236 |
+
* @param string $bucket Bucket name
|
237 |
+
* @return boolean
|
238 |
+
*/
|
239 |
+
public static function deleteBucket($bucket) {
|
240 |
+
$rest = new S3Request('DELETE', $bucket);
|
241 |
+
$rest = $rest->getResponse();
|
242 |
+
if ($rest->error === false && $rest->code !== 204)
|
243 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
244 |
+
if ($rest->error !== false) {
|
245 |
+
trigger_error(sprintf("S3::deleteBucket({$bucket}): [%s] %s",
|
246 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
247 |
+
return false;
|
248 |
+
}
|
249 |
+
return true;
|
250 |
+
}
|
251 |
+
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Create input info array for putObject()
|
255 |
+
*
|
256 |
+
* @param string $file Input file
|
257 |
+
* @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
|
258 |
+
* @return array | false
|
259 |
+
*/
|
260 |
+
public static function inputFile($file, $md5sum = true) {
|
261 |
+
if (!file_exists($file) || !is_file($file) || !is_readable($file)) {
|
262 |
+
trigger_error('S3::inputFile(): Unable to open input file: '.$file, E_USER_WARNING);
|
263 |
+
return false;
|
264 |
+
}
|
265 |
+
return array('file' => $file, 'size' => filesize($file),
|
266 |
+
'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum :
|
267 |
+
base64_encode(md5_file($file, true))) : '');
|
268 |
+
}
|
269 |
+
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Create input array info for putObject() with a resource
|
273 |
+
*
|
274 |
+
* @param string $resource Input resource to read from
|
275 |
+
* @param integer $bufferSize Input byte size
|
276 |
+
* @param string $md5sum MD5 hash to send (optional)
|
277 |
+
* @return array | false
|
278 |
+
*/
|
279 |
+
public static function inputResource(&$resource, $bufferSize, $md5sum = '') {
|
280 |
+
if (!is_resource($resource) || $bufferSize < 0) {
|
281 |
+
trigger_error('S3::inputResource(): Invalid resource or buffer size', E_USER_WARNING);
|
282 |
+
return false;
|
283 |
+
}
|
284 |
+
$input = array('size' => $bufferSize, 'md5sum' => $md5sum);
|
285 |
+
$input['fp'] =& $resource;
|
286 |
+
return $input;
|
287 |
+
}
|
288 |
+
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Put an object
|
292 |
+
*
|
293 |
+
* @param mixed $input Input data
|
294 |
+
* @param string $bucket Bucket name
|
295 |
+
* @param string $uri Object URI
|
296 |
+
* @param constant $acl ACL constant
|
297 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
298 |
+
* @param array $requestHeaders Array of request headers or content type as a string
|
299 |
+
* @return boolean
|
300 |
+
*/
|
301 |
+
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
|
302 |
+
if ($input === false) return false;
|
303 |
+
$rest = new S3Request('PUT', $bucket, $uri);
|
304 |
+
|
305 |
+
if (is_string($input)) $input = array(
|
306 |
+
'data' => $input, 'size' => strlen($input),
|
307 |
+
'md5sum' => base64_encode(md5($input, true))
|
308 |
+
);
|
309 |
+
|
310 |
+
// Data
|
311 |
+
if (isset($input['fp']))
|
312 |
+
$rest->fp =& $input['fp'];
|
313 |
+
elseif (isset($input['file']))
|
314 |
+
$rest->fp = @fopen($input['file'], 'rb');
|
315 |
+
elseif (isset($input['data']))
|
316 |
+
$rest->data = $input['data'];
|
317 |
+
|
318 |
+
// Content-Length (required)
|
319 |
+
if (isset($input['size']) && $input['size'] >= 0)
|
320 |
+
$rest->size = $input['size'];
|
321 |
+
else {
|
322 |
+
if (isset($input['file']))
|
323 |
+
$rest->size = filesize($input['file']);
|
324 |
+
elseif (isset($input['data']))
|
325 |
+
$rest->size = strlen($input['data']);
|
326 |
+
}
|
327 |
+
|
328 |
+
// Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
|
329 |
+
if (is_array($requestHeaders))
|
330 |
+
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
331 |
+
elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
|
332 |
+
$input['type'] = $requestHeaders;
|
333 |
+
|
334 |
+
// Content-Type
|
335 |
+
if (!isset($input['type'])) {
|
336 |
+
if (isset($requestHeaders['Content-Type']))
|
337 |
+
$input['type'] =& $requestHeaders['Content-Type'];
|
338 |
+
elseif (isset($input['file']))
|
339 |
+
$input['type'] = self::__getMimeType($input['file']);
|
340 |
+
else
|
341 |
+
$input['type'] = 'application/octet-stream';
|
342 |
+
}
|
343 |
+
|
344 |
+
// We need to post with Content-Length and Content-Type, MD5 is optional
|
345 |
+
if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false)) {
|
346 |
+
$rest->setHeader('Content-Type', $input['type']);
|
347 |
+
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
|
348 |
+
|
349 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
350 |
+
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
351 |
+
$rest->getResponse();
|
352 |
+
} else
|
353 |
+
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
|
354 |
+
|
355 |
+
if ($rest->response->error === false && $rest->response->code !== 200)
|
356 |
+
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
357 |
+
if ($rest->response->error !== false) {
|
358 |
+
trigger_error(sprintf("S3::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
|
359 |
+
return false;
|
360 |
+
}
|
361 |
+
return true;
|
362 |
+
}
|
363 |
+
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Put an object from a file (legacy function)
|
367 |
+
*
|
368 |
+
* @param string $file Input file path
|
369 |
+
* @param string $bucket Bucket name
|
370 |
+
* @param string $uri Object URI
|
371 |
+
* @param constant $acl ACL constant
|
372 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
373 |
+
* @param string $contentType Content type
|
374 |
+
* @return boolean
|
375 |
+
*/
|
376 |
+
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null) {
|
377 |
+
return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
|
378 |
+
}
|
379 |
+
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Put an object from a string (legacy function)
|
383 |
+
*
|
384 |
+
* @param string $string Input data
|
385 |
+
* @param string $bucket Bucket name
|
386 |
+
* @param string $uri Object URI
|
387 |
+
* @param constant $acl ACL constant
|
388 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
389 |
+
* @param string $contentType Content type
|
390 |
+
* @return boolean
|
391 |
+
*/
|
392 |
+
public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') {
|
393 |
+
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
|
394 |
+
}
|
395 |
+
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Get an object
|
399 |
+
*
|
400 |
+
* @param string $bucket Bucket name
|
401 |
+
* @param string $uri Object URI
|
402 |
+
* @param mixed $saveTo Filename or resource to write to
|
403 |
+
* @return mixed
|
404 |
+
*/
|
405 |
+
public static function getObject($bucket, $uri, $saveTo = false) {
|
406 |
+
$rest = new S3Request('GET', $bucket, $uri);
|
407 |
+
if ($saveTo !== false) {
|
408 |
+
if (is_resource($saveTo))
|
409 |
+
$rest->fp =& $saveTo;
|
410 |
+
else
|
411 |
+
if (($rest->fp = @fopen($saveTo, 'wb')) !== false)
|
412 |
+
$rest->file = realpath($saveTo);
|
413 |
+
else
|
414 |
+
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
|
415 |
+
}
|
416 |
+
if ($rest->response->error === false) $rest->getResponse();
|
417 |
+
|
418 |
+
if ($rest->response->error === false && $rest->response->code !== 200)
|
419 |
+
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
420 |
+
if ($rest->response->error !== false) {
|
421 |
+
trigger_error(sprintf("S3::getObject({$bucket}, {$uri}): [%s] %s",
|
422 |
+
$rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
|
423 |
+
return false;
|
424 |
+
}
|
425 |
+
return $rest->response;
|
426 |
+
}
|
427 |
+
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Get object information
|
431 |
+
*
|
432 |
+
* @param string $bucket Bucket name
|
433 |
+
* @param string $uri Object URI
|
434 |
+
* @param boolean $returnInfo Return response information
|
435 |
+
* @return mixed | false
|
436 |
+
*/
|
437 |
+
public static function getObjectInfo($bucket, $uri, $returnInfo = true) {
|
438 |
+
$rest = new S3Request('HEAD', $bucket, $uri);
|
439 |
+
$rest = $rest->getResponse();
|
440 |
+
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
|
441 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
442 |
+
if ($rest->error !== false) {
|
443 |
+
trigger_error(sprintf("S3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
|
444 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
445 |
+
return false;
|
446 |
+
}
|
447 |
+
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
|
448 |
+
}
|
449 |
+
|
450 |
+
|
451 |
+
/**
|
452 |
+
* Copy an object
|
453 |
+
*
|
454 |
+
* @param string $bucket Source bucket name
|
455 |
+
* @param string $uri Source object URI
|
456 |
+
* @param string $bucket Destination bucket name
|
457 |
+
* @param string $uri Destination object URI
|
458 |
+
* @param constant $acl ACL constant
|
459 |
+
* @param array $metaHeaders Optional array of x-amz-meta-* headers
|
460 |
+
* @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
|
461 |
+
* @return mixed | false
|
462 |
+
*/
|
463 |
+
public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
|
464 |
+
$rest = new S3Request('PUT', $bucket, $uri);
|
465 |
+
$rest->setHeader('Content-Length', 0);
|
466 |
+
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
467 |
+
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
468 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
469 |
+
$rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, $srcUri));
|
470 |
+
if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
|
471 |
+
$rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
|
472 |
+
$rest = $rest->getResponse();
|
473 |
+
if ($rest->error === false && $rest->code !== 200)
|
474 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
475 |
+
if ($rest->error !== false) {
|
476 |
+
trigger_error(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
|
477 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
478 |
+
return false;
|
479 |
+
}
|
480 |
+
return isset($rest->body->LastModified, $rest->body->ETag) ? array(
|
481 |
+
'time' => strtotime((string)$rest->body->LastModified),
|
482 |
+
'hash' => substr((string)$rest->body->ETag, 1, -1)
|
483 |
+
) : false;
|
484 |
+
}
|
485 |
+
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Set logging for a bucket
|
489 |
+
*
|
490 |
+
* @param string $bucket Bucket name
|
491 |
+
* @param string $targetBucket Target bucket (where logs are stored)
|
492 |
+
* @param string $targetPrefix Log prefix (e,g; domain.com-)
|
493 |
+
* @return boolean
|
494 |
+
*/
|
495 |
+
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null) {
|
496 |
+
// The S3 log delivery group has to be added to the target bucket's ACP
|
497 |
+
if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false) {
|
498 |
+
// Only add permissions to the target bucket when they do not exist
|
499 |
+
$aclWriteSet = false;
|
500 |
+
$aclReadSet = false;
|
501 |
+
foreach ($acp['acl'] as $acl)
|
502 |
+
if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery') {
|
503 |
+
if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
|
504 |
+
elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
|
505 |
+
}
|
506 |
+
if (!$aclWriteSet) $acp['acl'][] = array(
|
507 |
+
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
|
508 |
+
);
|
509 |
+
if (!$aclReadSet) $acp['acl'][] = array(
|
510 |
+
'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
|
511 |
+
);
|
512 |
+
if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
|
513 |
+
}
|
514 |
+
|
515 |
+
$dom = new DOMDocument;
|
516 |
+
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
|
517 |
+
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
|
518 |
+
if ($targetBucket !== null) {
|
519 |
+
if ($targetPrefix == null) $targetPrefix = $bucket . '-';
|
520 |
+
$loggingEnabled = $dom->createElement('LoggingEnabled');
|
521 |
+
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
|
522 |
+
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
|
523 |
+
// TODO: Add TargetGrants?
|
524 |
+
$bucketLoggingStatus->appendChild($loggingEnabled);
|
525 |
+
}
|
526 |
+
$dom->appendChild($bucketLoggingStatus);
|
527 |
+
|
528 |
+
$rest = new S3Request('PUT', $bucket, '');
|
529 |
+
$rest->setParameter('logging', null);
|
530 |
+
$rest->data = $dom->saveXML();
|
531 |
+
$rest->size = strlen($rest->data);
|
532 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
533 |
+
$rest = $rest->getResponse();
|
534 |
+
if ($rest->error === false && $rest->code !== 200)
|
535 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
536 |
+
if ($rest->error !== false) {
|
537 |
+
trigger_error(sprintf("S3::setBucketLogging({$bucket}, {$uri}): [%s] %s",
|
538 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
539 |
+
return false;
|
540 |
+
}
|
541 |
+
return true;
|
542 |
+
}
|
543 |
+
|
544 |
+
|
545 |
+
/**
|
546 |
+
* Get logging status for a bucket
|
547 |
+
*
|
548 |
+
* This will return false if logging is not enabled.
|
549 |
+
* Note: To enable logging, you also need to grant write access to the log group
|
550 |
+
*
|
551 |
+
* @param string $bucket Bucket name
|
552 |
+
* @return array | false
|
553 |
+
*/
|
554 |
+
public static function getBucketLogging($bucket) {
|
555 |
+
$rest = new S3Request('GET', $bucket, '');
|
556 |
+
$rest->setParameter('logging', null);
|
557 |
+
$rest = $rest->getResponse();
|
558 |
+
if ($rest->error === false && $rest->code !== 200)
|
559 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
560 |
+
if ($rest->error !== false) {
|
561 |
+
trigger_error(sprintf("S3::getBucketLogging({$bucket}): [%s] %s",
|
562 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
563 |
+
return false;
|
564 |
+
}
|
565 |
+
if (!isset($rest->body->LoggingEnabled)) return false; // No logging
|
566 |
+
return array(
|
567 |
+
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
|
568 |
+
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
|
569 |
+
);
|
570 |
+
}
|
571 |
+
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Disable bucket logging
|
575 |
+
*
|
576 |
+
* @param string $bucket Bucket name
|
577 |
+
* @return boolean
|
578 |
+
*/
|
579 |
+
public static function disableBucketLogging($bucket) {
|
580 |
+
return self::setBucketLogging($bucket, null);
|
581 |
+
}
|
582 |
+
|
583 |
+
|
584 |
+
/**
|
585 |
+
* Get a bucket's location
|
586 |
+
*
|
587 |
+
* @param string $bucket Bucket name
|
588 |
+
* @return string | false
|
589 |
+
*/
|
590 |
+
public static function getBucketLocation($bucket) {
|
591 |
+
$rest = new S3Request('GET', $bucket, '');
|
592 |
+
$rest->setParameter('location', null);
|
593 |
+
$rest = $rest->getResponse();
|
594 |
+
if ($rest->error === false && $rest->code !== 200)
|
595 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
596 |
+
if ($rest->error !== false) {
|
597 |
+
trigger_error(sprintf("S3::getBucketLocation({$bucket}): [%s] %s",
|
598 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
599 |
+
return false;
|
600 |
+
}
|
601 |
+
return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
|
602 |
+
}
|
603 |
+
|
604 |
+
|
605 |
+
/**
|
606 |
+
* Set object or bucket Access Control Policy
|
607 |
+
*
|
608 |
+
* @param string $bucket Bucket name
|
609 |
+
* @param string $uri Object URI
|
610 |
+
* @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
|
611 |
+
* @return boolean
|
612 |
+
*/
|
613 |
+
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array()) {
|
614 |
+
$dom = new DOMDocument;
|
615 |
+
$dom->formatOutput = true;
|
616 |
+
$accessControlPolicy = $dom->createElement('AccessControlPolicy');
|
617 |
+
$accessControlList = $dom->createElement('AccessControlList');
|
618 |
+
|
619 |
+
// It seems the owner has to be passed along too
|
620 |
+
$owner = $dom->createElement('Owner');
|
621 |
+
$owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
|
622 |
+
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
|
623 |
+
$accessControlPolicy->appendChild($owner);
|
624 |
+
|
625 |
+
foreach ($acp['acl'] as $g) {
|
626 |
+
$grant = $dom->createElement('Grant');
|
627 |
+
$grantee = $dom->createElement('Grantee');
|
628 |
+
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
629 |
+
if (isset($g['id'])) { // CanonicalUser (DisplayName is omitted)
|
630 |
+
$grantee->setAttribute('xsi:type', 'CanonicalUser');
|
631 |
+
$grantee->appendChild($dom->createElement('ID', $g['id']));
|
632 |
+
} elseif (isset($g['email'])) { // AmazonCustomerByEmail
|
633 |
+
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
|
634 |
+
$grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
|
635 |
+
} elseif ($g['type'] == 'Group') { // Group
|
636 |
+
$grantee->setAttribute('xsi:type', 'Group');
|
637 |
+
$grantee->appendChild($dom->createElement('URI', $g['uri']));
|
638 |
+
}
|
639 |
+
$grant->appendChild($grantee);
|
640 |
+
$grant->appendChild($dom->createElement('Permission', $g['permission']));
|
641 |
+
$accessControlList->appendChild($grant);
|
642 |
+
}
|
643 |
+
|
644 |
+
$accessControlPolicy->appendChild($accessControlList);
|
645 |
+
$dom->appendChild($accessControlPolicy);
|
646 |
+
|
647 |
+
$rest = new S3Request('PUT', $bucket, $uri);
|
648 |
+
$rest->setParameter('acl', null);
|
649 |
+
$rest->data = $dom->saveXML();
|
650 |
+
$rest->size = strlen($rest->data);
|
651 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
652 |
+
$rest = $rest->getResponse();
|
653 |
+
if ($rest->error === false && $rest->code !== 200)
|
654 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
655 |
+
if ($rest->error !== false) {
|
656 |
+
trigger_error(sprintf("S3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
657 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
658 |
+
return false;
|
659 |
+
}
|
660 |
+
return true;
|
661 |
+
}
|
662 |
+
|
663 |
+
|
664 |
+
/**
|
665 |
+
* Get object or bucket Access Control Policy
|
666 |
+
*
|
667 |
+
* @param string $bucket Bucket name
|
668 |
+
* @param string $uri Object URI
|
669 |
+
* @return mixed | false
|
670 |
+
*/
|
671 |
+
public static function getAccessControlPolicy($bucket, $uri = '') {
|
672 |
+
$rest = new S3Request('GET', $bucket, $uri);
|
673 |
+
$rest->setParameter('acl', null);
|
674 |
+
$rest = $rest->getResponse();
|
675 |
+
if ($rest->error === false && $rest->code !== 200)
|
676 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
677 |
+
if ($rest->error !== false) {
|
678 |
+
trigger_error(sprintf("S3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
|
679 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
680 |
+
return false;
|
681 |
+
}
|
682 |
+
|
683 |
+
$acp = array();
|
684 |
+
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) {
|
685 |
+
$acp['owner'] = array(
|
686 |
+
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
|
687 |
+
);
|
688 |
+
}
|
689 |
+
if (isset($rest->body->AccessControlList)) {
|
690 |
+
$acp['acl'] = array();
|
691 |
+
foreach ($rest->body->AccessControlList->Grant as $grant) {
|
692 |
+
foreach ($grant->Grantee as $grantee) {
|
693 |
+
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
|
694 |
+
$acp['acl'][] = array(
|
695 |
+
'type' => 'CanonicalUser',
|
696 |
+
'id' => (string)$grantee->ID,
|
697 |
+
'name' => (string)$grantee->DisplayName,
|
698 |
+
'permission' => (string)$grant->Permission
|
699 |
+
);
|
700 |
+
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
|
701 |
+
$acp['acl'][] = array(
|
702 |
+
'type' => 'AmazonCustomerByEmail',
|
703 |
+
'email' => (string)$grantee->EmailAddress,
|
704 |
+
'permission' => (string)$grant->Permission
|
705 |
+
);
|
706 |
+
elseif (isset($grantee->URI)) // Group
|
707 |
+
$acp['acl'][] = array(
|
708 |
+
'type' => 'Group',
|
709 |
+
'uri' => (string)$grantee->URI,
|
710 |
+
'permission' => (string)$grant->Permission
|
711 |
+
);
|
712 |
+
else continue;
|
713 |
+
}
|
714 |
+
}
|
715 |
+
}
|
716 |
+
return $acp;
|
717 |
+
}
|
718 |
+
|
719 |
+
|
720 |
+
/**
|
721 |
+
* Delete an object
|
722 |
+
*
|
723 |
+
* @param string $bucket Bucket name
|
724 |
+
* @param string $uri Object URI
|
725 |
+
* @return boolean
|
726 |
+
*/
|
727 |
+
public static function deleteObject($bucket, $uri) {
|
728 |
+
$rest = new S3Request('DELETE', $bucket, $uri);
|
729 |
+
$rest = $rest->getResponse();
|
730 |
+
if ($rest->error === false && $rest->code !== 204)
|
731 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
732 |
+
if ($rest->error !== false) {
|
733 |
+
trigger_error(sprintf("S3::deleteObject(): [%s] %s",
|
734 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
735 |
+
return false;
|
736 |
+
}
|
737 |
+
return true;
|
738 |
+
}
|
739 |
+
|
740 |
+
|
741 |
+
/**
|
742 |
+
* Get a query string authenticated URL
|
743 |
+
*
|
744 |
+
* @param string $bucket Bucket name
|
745 |
+
* @param string $uri Object URI
|
746 |
+
* @param integer $lifetime Lifetime in seconds
|
747 |
+
* @param boolean $hostBucket Use the bucket name as the hostname
|
748 |
+
* @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
|
749 |
+
* @return string
|
750 |
+
*/
|
751 |
+
public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false) {
|
752 |
+
$expires = time() + $lifetime;
|
753 |
+
$uri = str_replace('%2F', '/', rawurlencode($uri)); // URI should be encoded (thanks Sean O'Dea)
|
754 |
+
return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
|
755 |
+
$hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
|
756 |
+
urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
|
757 |
+
}
|
758 |
+
|
759 |
+
/**
|
760 |
+
* Get upload POST parameters for form uploads
|
761 |
+
*
|
762 |
+
* @param string $bucket Bucket name
|
763 |
+
* @param string $uriPrefix Object URI prefix
|
764 |
+
* @param constant $acl ACL constant
|
765 |
+
* @param integer $lifetime Lifetime in seconds
|
766 |
+
* @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
|
767 |
+
* @param string $successRedirect Redirect URL or 200 / 201 status code
|
768 |
+
* @param array $amzHeaders Array of x-amz-meta-* headers
|
769 |
+
* @param array $headers Array of request headers or content type as a string
|
770 |
+
* @param boolean $flashVars Includes additional "Filename" variable posted by Flash
|
771 |
+
* @return object
|
772 |
+
*/
|
773 |
+
public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600, $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false) {
|
774 |
+
// Create policy object
|
775 |
+
$policy = new stdClass;
|
776 |
+
$policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
|
777 |
+
$policy->conditions = array();
|
778 |
+
$obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
|
779 |
+
$obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
|
780 |
+
|
781 |
+
$obj = new stdClass; // 200 for non-redirect uploads
|
782 |
+
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
783 |
+
$obj->success_action_status = (string)$successRedirect;
|
784 |
+
else // URL
|
785 |
+
$obj->success_action_redirect = $successRedirect;
|
786 |
+
array_push($policy->conditions, $obj);
|
787 |
+
|
788 |
+
array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
|
789 |
+
if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
|
790 |
+
foreach (array_keys($headers) as $headerKey)
|
791 |
+
array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
|
792 |
+
foreach ($amzHeaders as $headerKey => $headerVal) {
|
793 |
+
$obj = new stdClass; $obj->{$headerKey} = (string)$headerVal; array_push($policy->conditions, $obj);
|
794 |
+
}
|
795 |
+
array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
|
796 |
+
$policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
|
797 |
+
|
798 |
+
// Create parameters
|
799 |
+
$params = new stdClass;
|
800 |
+
$params->AWSAccessKeyId = self::$__accessKey;
|
801 |
+
$params->key = $uriPrefix.'${filename}';
|
802 |
+
$params->acl = $acl;
|
803 |
+
$params->policy = $policy; unset($policy);
|
804 |
+
$params->signature = self::__getHash($params->policy);
|
805 |
+
if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
|
806 |
+
$params->success_action_status = (string)$successRedirect;
|
807 |
+
else
|
808 |
+
$params->success_action_redirect = $successRedirect;
|
809 |
+
foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
810 |
+
foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
|
811 |
+
return $params;
|
812 |
+
}
|
813 |
+
|
814 |
+
/**
|
815 |
+
* Create a CloudFront distribution
|
816 |
+
*
|
817 |
+
* @param string $bucket Bucket name
|
818 |
+
* @param boolean $enabled Enabled (true/false)
|
819 |
+
* @param array $cnames Array containing CNAME aliases
|
820 |
+
* @param string $comment Use the bucket name as the hostname
|
821 |
+
* @return array | false
|
822 |
+
*/
|
823 |
+
public static function createDistribution($bucket, $enabled = true, $cnames = array(), $comment = '') {
|
824 |
+
self::$useSSL = true; // CloudFront requires SSL
|
825 |
+
$rest = new S3Request('POST', '', '2008-06-30/distribution', 'cloudfront.amazonaws.com');
|
826 |
+
$rest->data = self::__getCloudFrontDistributionConfigXML($bucket.'.s3.amazonaws.com', $enabled, $comment, (string)microtime(true), $cnames);
|
827 |
+
$rest->size = strlen($rest->data);
|
828 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
829 |
+
$rest = self::__getCloudFrontResponse($rest);
|
830 |
+
|
831 |
+
if ($rest->error === false && $rest->code !== 201)
|
832 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
833 |
+
if ($rest->error !== false) {
|
834 |
+
trigger_error(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", '$comment'): [%s] %s",
|
835 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
836 |
+
return false;
|
837 |
+
} elseif ($rest->body instanceof SimpleXMLElement)
|
838 |
+
return self::__parseCloudFrontDistributionConfig($rest->body);
|
839 |
+
return false;
|
840 |
+
}
|
841 |
+
|
842 |
+
|
843 |
+
/**
|
844 |
+
* Get CloudFront distribution info
|
845 |
+
*
|
846 |
+
* @param string $distributionId Distribution ID from listDistributions()
|
847 |
+
* @return array | false
|
848 |
+
*/
|
849 |
+
public static function getDistribution($distributionId) {
|
850 |
+
self::$useSSL = true; // CloudFront requires SSL
|
851 |
+
$rest = new S3Request('GET', '', '2008-06-30/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
|
852 |
+
$rest = self::__getCloudFrontResponse($rest);
|
853 |
+
|
854 |
+
if ($rest->error === false && $rest->code !== 200)
|
855 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
856 |
+
if ($rest->error !== false) {
|
857 |
+
trigger_error(sprintf("S3::getDistribution($distributionId): [%s] %s",
|
858 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
859 |
+
return false;
|
860 |
+
} elseif ($rest->body instanceof SimpleXMLElement) {
|
861 |
+
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
862 |
+
$dist['hash'] = $rest->headers['hash'];
|
863 |
+
return $dist;
|
864 |
+
}
|
865 |
+
return false;
|
866 |
+
}
|
867 |
+
|
868 |
+
|
869 |
+
/**
|
870 |
+
* Update a CloudFront distribution
|
871 |
+
*
|
872 |
+
* @param array $dist Distribution array info identical to output of getDistribution()
|
873 |
+
* @return array | false
|
874 |
+
*/
|
875 |
+
public static function updateDistribution($dist) {
|
876 |
+
self::$useSSL = true; // CloudFront requires SSL
|
877 |
+
$rest = new S3Request('PUT', '', '2008-06-30/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
|
878 |
+
$rest->data = self::__getCloudFrontDistributionConfigXML($dist['origin'], $dist['enabled'], $dist['comment'], $dist['callerReference'], $dist['cnames']);
|
879 |
+
$rest->size = strlen($rest->data);
|
880 |
+
$rest->setHeader('If-Match', $dist['hash']);
|
881 |
+
$rest = self::__getCloudFrontResponse($rest);
|
882 |
+
|
883 |
+
if ($rest->error === false && $rest->code !== 200)
|
884 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
885 |
+
if ($rest->error !== false) {
|
886 |
+
trigger_error(sprintf("S3::updateDistribution({$dist['id']}, ".(int)$enabled.", '$comment'): [%s] %s",
|
887 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
888 |
+
return false;
|
889 |
+
} else {
|
890 |
+
$dist = self::__parseCloudFrontDistributionConfig($rest->body);
|
891 |
+
$dist['hash'] = $rest->headers['hash'];
|
892 |
+
return $dist;
|
893 |
+
}
|
894 |
+
return false;
|
895 |
+
}
|
896 |
+
|
897 |
+
|
898 |
+
/**
|
899 |
+
* Delete a CloudFront distribution
|
900 |
+
*
|
901 |
+
* @param array $dist Distribution array info identical to output of getDistribution()
|
902 |
+
* @return boolean
|
903 |
+
*/
|
904 |
+
public static function deleteDistribution($dist) {
|
905 |
+
self::$useSSL = true; // CloudFront requires SSL
|
906 |
+
$rest = new S3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
|
907 |
+
$rest->setHeader('If-Match', $dist['hash']);
|
908 |
+
$rest = self::__getCloudFrontResponse($rest);
|
909 |
+
|
910 |
+
if ($rest->error === false && $rest->code !== 204)
|
911 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
912 |
+
if ($rest->error !== false) {
|
913 |
+
trigger_error(sprintf("S3::deleteDistribution({$dist['id']}): [%s] %s",
|
914 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
915 |
+
return false;
|
916 |
+
}
|
917 |
+
return true;
|
918 |
+
}
|
919 |
+
|
920 |
+
|
921 |
+
/**
|
922 |
+
* Get a list of CloudFront distributions
|
923 |
+
*
|
924 |
+
* @return array
|
925 |
+
*/
|
926 |
+
public static function listDistributions() {
|
927 |
+
self::$useSSL = true; // CloudFront requires SSL
|
928 |
+
$rest = new S3Request('GET', '', '2008-06-30/distribution', 'cloudfront.amazonaws.com');
|
929 |
+
$rest = self::__getCloudFrontResponse($rest);
|
930 |
+
|
931 |
+
if ($rest->error === false && $rest->code !== 200)
|
932 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
933 |
+
if ($rest->error !== false) {
|
934 |
+
trigger_error(sprintf("S3::listDistributions(): [%s] %s",
|
935 |
+
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
|
936 |
+
return false;
|
937 |
+
} elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary)) {
|
938 |
+
$list = array();
|
939 |
+
if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated)) {
|
940 |
+
//$info['marker'] = (string)$rest->body->Marker;
|
941 |
+
//$info['maxItems'] = (int)$rest->body->MaxItems;
|
942 |
+
//$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
|
943 |
+
}
|
944 |
+
foreach ($rest->body->DistributionSummary as $summary) {
|
945 |
+
$list[(string)$summary->Id] = self::__parseCloudFrontDistributionConfig($summary);
|
946 |
+
}
|
947 |
+
return $list;
|
948 |
+
}
|
949 |
+
return array();
|
950 |
+
}
|
951 |
+
|
952 |
+
|
953 |
+
/**
|
954 |
+
* Get a DistributionConfig DOMDocument
|
955 |
+
*
|
956 |
+
* @internal Used to create XML in createDistribution() and updateDistribution()
|
957 |
+
* @param string $bucket Origin bucket
|
958 |
+
* @param boolean $enabled Enabled (true/false)
|
959 |
+
* @param string $comment Comment to append
|
960 |
+
* @param string $callerReference Caller reference
|
961 |
+
* @param array $cnames Array of CNAME aliases
|
962 |
+
* @return string
|
963 |
+
*/
|
964 |
+
private static function __getCloudFrontDistributionConfigXML($bucket, $enabled, $comment, $callerReference = '0', $cnames = array()) {
|
965 |
+
$dom = new DOMDocument('1.0', 'UTF-8');
|
966 |
+
$dom->formatOutput = true;
|
967 |
+
$distributionConfig = $dom->createElement('DistributionConfig');
|
968 |
+
$distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2008-06-30/');
|
969 |
+
$distributionConfig->appendChild($dom->createElement('Origin', $bucket));
|
970 |
+
$distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
|
971 |
+
foreach ($cnames as $cname)
|
972 |
+
$distributionConfig->appendChild($dom->createElement('CNAME', $cname));
|
973 |
+
if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
|
974 |
+
$distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
|
975 |
+
$dom->appendChild($distributionConfig);
|
976 |
+
return $dom->saveXML();
|
977 |
+
}
|
978 |
+
|
979 |
+
|
980 |
+
/**
|
981 |
+
* Parse a CloudFront distribution config
|
982 |
+
*
|
983 |
+
* @internal Used to parse the CloudFront DistributionConfig node to an array
|
984 |
+
* @param object &$node DOMNode
|
985 |
+
* @return array
|
986 |
+
*/
|
987 |
+
private static function __parseCloudFrontDistributionConfig(&$node) {
|
988 |
+
$dist = array();
|
989 |
+
if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName)) {
|
990 |
+
$dist['id'] = (string)$node->Id;
|
991 |
+
$dist['status'] = (string)$node->Status;
|
992 |
+
$dist['time'] = strtotime((string)$node->LastModifiedTime);
|
993 |
+
$dist['domain'] = (string)$node->DomainName;
|
994 |
+
}
|
995 |
+
if (isset($node->CallerReference))
|
996 |
+
$dist['callerReference'] = (string)$node->CallerReference;
|
997 |
+
if (isset($node->Comment))
|
998 |
+
$dist['comment'] = (string)$node->Comment;
|
999 |
+
if (isset($node->Enabled, $node->Origin)) {
|
1000 |
+
$dist['origin'] = (string)$node->Origin;
|
1001 |
+
$dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
|
1002 |
+
} elseif (isset($node->DistributionConfig)) {
|
1003 |
+
$dist = array_merge($dist, self::__parseCloudFrontDistributionConfig($node->DistributionConfig));
|
1004 |
+
}
|
1005 |
+
if (isset($node->CNAME)) {
|
1006 |
+
$dist['cnames'] = array();
|
1007 |
+
foreach ($node->CNAME as $cname) $dist['cnames'][(string)$cname] = (string)$cname;
|
1008 |
+
}
|
1009 |
+
return $dist;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
|
1013 |
+
/**
|
1014 |
+
* Grab CloudFront response
|
1015 |
+
*
|
1016 |
+
* @internal Used to parse the CloudFront S3Request::getResponse() output
|
1017 |
+
* @param object &$rest S3Request instance
|
1018 |
+
* @return object
|
1019 |
+
*/
|
1020 |
+
private static function __getCloudFrontResponse(&$rest) {
|
1021 |
+
$rest->getResponse();
|
1022 |
+
if ($rest->response->error === false && isset($rest->response->body) &&
|
1023 |
+
is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml') {
|
1024 |
+
$rest->response->body = simplexml_load_string($rest->response->body);
|
1025 |
+
// Grab CloudFront errors
|
1026 |
+
if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
|
1027 |
+
$rest->response->body->Error->Message)) {
|
1028 |
+
$rest->response->error = array(
|
1029 |
+
'code' => (string)$rest->response->body->Error->Code,
|
1030 |
+
'message' => (string)$rest->response->body->Error->Message
|
1031 |
+
);
|
1032 |
+
unset($rest->response->body);
|
1033 |
+
}
|
1034 |
+
}
|
1035 |
+
return $rest->response;
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
|
1039 |
+
/**
|
1040 |
+
* Get MIME type for file
|
1041 |
+
*
|
1042 |
+
* @internal Used to get mime types
|
1043 |
+
* @param string &$file File path
|
1044 |
+
* @return string
|
1045 |
+
*/
|
1046 |
+
public static function __getMimeType(&$file) {
|
1047 |
+
$type = false;
|
1048 |
+
// Fileinfo documentation says fileinfo_open() will use the
|
1049 |
+
// MAGIC env var for the magic file
|
1050 |
+
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
|
1051 |
+
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) {
|
1052 |
+
if (($type = finfo_file($finfo, $file)) !== false) {
|
1053 |
+
// Remove the charset and grab the last content-type
|
1054 |
+
$type = explode(' ', str_replace('; charset=', ';charset=', $type));
|
1055 |
+
$type = array_pop($type);
|
1056 |
+
$type = explode(';', $type);
|
1057 |
+
$type = trim(array_shift($type));
|
1058 |
+
}
|
1059 |
+
finfo_close($finfo);
|
1060 |
+
|
1061 |
+
// If anyone is still using mime_content_type()
|
1062 |
+
} elseif (function_exists('mime_content_type'))
|
1063 |
+
$type = trim(mime_content_type($file));
|
1064 |
+
|
1065 |
+
if ($type !== false && strlen($type) > 0) return $type;
|
1066 |
+
|
1067 |
+
// Otherwise do it the old fashioned way
|
1068 |
+
static $exts = array(
|
1069 |
+
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
|
1070 |
+
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
|
1071 |
+
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
|
1072 |
+
'zip' => 'application/zip', 'gz' => 'application/x-gzip',
|
1073 |
+
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
|
1074 |
+
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
|
1075 |
+
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
|
1076 |
+
'css' => 'text/css', 'js' => 'text/javascript',
|
1077 |
+
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
|
1078 |
+
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
|
1079 |
+
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
|
1080 |
+
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
|
1081 |
+
);
|
1082 |
+
$ext = strtolower(pathInfo($file, PATHINFO_EXTENSION));
|
1083 |
+
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
|
1084 |
+
}
|
1085 |
+
|
1086 |
+
|
1087 |
+
/**
|
1088 |
+
* Generate the auth string: "AWS AccessKey:Signature"
|
1089 |
+
*
|
1090 |
+
* @internal Used by S3Request::getResponse()
|
1091 |
+
* @param string $string String to sign
|
1092 |
+
* @return string
|
1093 |
+
*/
|
1094 |
+
public static function __getSignature($string) {
|
1095 |
+
return 'AWS '.self::$__accessKey.':'.self::__getHash($string);
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
|
1099 |
+
/**
|
1100 |
+
* Creates a HMAC-SHA1 hash
|
1101 |
+
*
|
1102 |
+
* This uses the hash extension if loaded
|
1103 |
+
*
|
1104 |
+
* @internal Used by __getSignature()
|
1105 |
+
* @param string $string String to sign
|
1106 |
+
* @return string
|
1107 |
+
*/
|
1108 |
+
private static function __getHash($string) {
|
1109 |
+
return base64_encode(extension_loaded('hash') ?
|
1110 |
+
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
|
1111 |
+
(str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
|
1112 |
+
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
|
1113 |
+
(str_repeat(chr(0x36), 64))) . $string)))));
|
1114 |
+
}
|
1115 |
+
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
final class S3Request {
|
1119 |
+
private $verb, $bucket, $uri, $resource = '', $parameters = array(),
|
1120 |
+
$amzHeaders = array(), $headers = array(
|
1121 |
+
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
|
1122 |
+
);
|
1123 |
+
public $fp = false, $size = 0, $data = false, $response;
|
1124 |
+
|
1125 |
+
|
1126 |
+
/**
|
1127 |
+
* Constructor
|
1128 |
+
*
|
1129 |
+
* @param string $verb Verb
|
1130 |
+
* @param string $bucket Bucket name
|
1131 |
+
* @param string $uri Object URI
|
1132 |
+
* @return mixed
|
1133 |
+
*/
|
1134 |
+
function __construct($verb, $bucket = '', $uri = '', $defaultHost = 's3.amazonaws.com') {
|
1135 |
+
$this->verb = $verb;
|
1136 |
+
$this->bucket = strtolower($bucket);
|
1137 |
+
$this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
|
1138 |
+
|
1139 |
+
if ($this->bucket !== '') {
|
1140 |
+
$this->headers['Host'] = $this->bucket.'.'.$defaultHost;
|
1141 |
+
$this->resource = '/'.$this->bucket.$this->uri;
|
1142 |
+
} else {
|
1143 |
+
$this->headers['Host'] = $defaultHost;
|
1144 |
+
//$this->resource = strlen($this->uri) > 1 ? '/'.$this->bucket.$this->uri : $this->uri;
|
1145 |
+
$this->resource = $this->uri;
|
1146 |
+
}
|
1147 |
+
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
|
1148 |
+
|
1149 |
+
$this->response = new STDClass;
|
1150 |
+
$this->response->error = false;
|
1151 |
+
}
|
1152 |
+
|
1153 |
+
|
1154 |
+
/**
|
1155 |
+
* Set request parameter
|
1156 |
+
*
|
1157 |
+
* @param string $key Key
|
1158 |
+
* @param string $value Value
|
1159 |
+
* @return void
|
1160 |
+
*/
|
1161 |
+
public function setParameter($key, $value) {
|
1162 |
+
$this->parameters[$key] = $value;
|
1163 |
+
}
|
1164 |
+
|
1165 |
+
|
1166 |
+
/**
|
1167 |
+
* Set request header
|
1168 |
+
*
|
1169 |
+
* @param string $key Key
|
1170 |
+
* @param string $value Value
|
1171 |
+
* @return void
|
1172 |
+
*/
|
1173 |
+
public function setHeader($key, $value) {
|
1174 |
+
$this->headers[$key] = $value;
|
1175 |
+
}
|
1176 |
+
|
1177 |
+
|
1178 |
+
/**
|
1179 |
+
* Set x-amz-meta-* header
|
1180 |
+
*
|
1181 |
+
* @param string $key Key
|
1182 |
+
* @param string $value Value
|
1183 |
+
* @return void
|
1184 |
+
*/
|
1185 |
+
public function setAmzHeader($key, $value) {
|
1186 |
+
$this->amzHeaders[$key] = $value;
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
|
1190 |
+
/**
|
1191 |
+
* Get the S3 response
|
1192 |
+
*
|
1193 |
+
* @return object | false
|
1194 |
+
*/
|
1195 |
+
public function getResponse() {
|
1196 |
+
$query = '';
|
1197 |
+
if (sizeof($this->parameters) > 0) {
|
1198 |
+
$query = substr($this->uri, -1) !== '?' ? '?' : '&';
|
1199 |
+
foreach ($this->parameters as $var => $value)
|
1200 |
+
if ($value == null || $value == '') $query .= $var.'&';
|
1201 |
+
// Parameters should be encoded (thanks Sean O'Dea)
|
1202 |
+
else $query .= $var.'='.rawurlencode($value).'&';
|
1203 |
+
$query = substr($query, 0, -1);
|
1204 |
+
$this->uri .= $query;
|
1205 |
+
|
1206 |
+
if (array_key_exists('acl', $this->parameters) ||
|
1207 |
+
array_key_exists('location', $this->parameters) ||
|
1208 |
+
array_key_exists('torrent', $this->parameters) ||
|
1209 |
+
array_key_exists('logging', $this->parameters))
|
1210 |
+
$this->resource .= $query;
|
1211 |
+
}
|
1212 |
+
$url = ((S3::$useSSL && extension_loaded('openssl')) ?
|
1213 |
+
'https://':'http://').$this->headers['Host'].$this->uri;
|
1214 |
+
//var_dump($this->bucket, $this->uri, $this->resource, $url);
|
1215 |
+
|
1216 |
+
// Basic setup
|
1217 |
+
$curl = curl_init();
|
1218 |
+
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
|
1219 |
+
|
1220 |
+
if (S3::$useSSL) {
|
1221 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
|
1222 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
|
1223 |
+
}
|
1224 |
+
|
1225 |
+
curl_setopt($curl, CURLOPT_URL, $url);
|
1226 |
+
|
1227 |
+
// Headers
|
1228 |
+
$headers = array(); $amz = array();
|
1229 |
+
foreach ($this->amzHeaders as $header => $value)
|
1230 |
+
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1231 |
+
foreach ($this->headers as $header => $value)
|
1232 |
+
if (strlen($value) > 0) $headers[] = $header.': '.$value;
|
1233 |
+
|
1234 |
+
// Collect AMZ headers for signature
|
1235 |
+
foreach ($this->amzHeaders as $header => $value)
|
1236 |
+
if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
|
1237 |
+
|
1238 |
+
// AMZ headers must be sorted
|
1239 |
+
if (sizeof($amz) > 0) {
|
1240 |
+
sort($amz);
|
1241 |
+
$amz = "\n".implode("\n", $amz);
|
1242 |
+
} else $amz = '';
|
1243 |
+
|
1244 |
+
// Authorization string (CloudFront stringToSign should only contain a date)
|
1245 |
+
$headers[] = 'Authorization: ' . S3::__getSignature(
|
1246 |
+
$this->headers['Host'] == 'cloudfront.amazonaws.com' ? $this->headers['Date'] :
|
1247 |
+
$this->verb."\n".$this->headers['Content-MD5']."\n".
|
1248 |
+
$this->headers['Content-Type']."\n".$this->headers['Date'].$amz."\n".$this->resource
|
1249 |
+
);
|
1250 |
+
|
1251 |
+
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
1252 |
+
curl_setopt($curl, CURLOPT_HEADER, false);
|
1253 |
+
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
|
1254 |
+
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
|
1255 |
+
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
|
1256 |
+
//curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
1257 |
+
|
1258 |
+
// Request types
|
1259 |
+
switch ($this->verb) {
|
1260 |
+
case 'GET': break;
|
1261 |
+
case 'PUT': case 'POST': // POST only used for CloudFront
|
1262 |
+
if ($this->fp !== false) {
|
1263 |
+
curl_setopt($curl, CURLOPT_PUT, true);
|
1264 |
+
curl_setopt($curl, CURLOPT_INFILE, $this->fp);
|
1265 |
+
if ($this->size >= 0)
|
1266 |
+
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
|
1267 |
+
} elseif ($this->data !== false) {
|
1268 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1269 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
|
1270 |
+
if ($this->size >= 0)
|
1271 |
+
curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size);
|
1272 |
+
} else
|
1273 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
|
1274 |
+
break;
|
1275 |
+
case 'HEAD':
|
1276 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
|
1277 |
+
curl_setopt($curl, CURLOPT_NOBODY, true);
|
1278 |
+
break;
|
1279 |
+
case 'DELETE':
|
1280 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
1281 |
+
break;
|
1282 |
+
default: break;
|
1283 |
+
}
|
1284 |
+
|
1285 |
+
// Execute, grab errors
|
1286 |
+
if (curl_exec($curl))
|
1287 |
+
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
1288 |
+
else
|
1289 |
+
$this->response->error = array(
|
1290 |
+
'code' => curl_errno($curl),
|
1291 |
+
'message' => curl_error($curl),
|
1292 |
+
'resource' => $this->resource
|
1293 |
+
);
|
1294 |
+
|
1295 |
+
@curl_close($curl);
|
1296 |
+
|
1297 |
+
// Parse body into XML
|
1298 |
+
if ($this->response->error === false && isset($this->response->headers['type']) &&
|
1299 |
+
$this->response->headers['type'] == 'application/xml' && isset($this->response->body)) {
|
1300 |
+
$this->response->body = simplexml_load_string($this->response->body);
|
1301 |
+
|
1302 |
+
// Grab S3 errors
|
1303 |
+
if (!in_array($this->response->code, array(200, 204)) &&
|
1304 |
+
isset($this->response->body->Code, $this->response->body->Message)) {
|
1305 |
+
$this->response->error = array(
|
1306 |
+
'code' => (string)$this->response->body->Code,
|
1307 |
+
'message' => (string)$this->response->body->Message
|
1308 |
+
);
|
1309 |
+
if (isset($this->response->body->Resource))
|
1310 |
+
$this->response->error['resource'] = (string)$this->response->body->Resource;
|
1311 |
+
unset($this->response->body);
|
1312 |
+
}
|
1313 |
+
}
|
1314 |
+
|
1315 |
+
// Clean up file resources
|
1316 |
+
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
|
1317 |
+
|
1318 |
+
return $this->response;
|
1319 |
+
}
|
1320 |
+
|
1321 |
+
|
1322 |
+
/**
|
1323 |
+
* CURL write callback
|
1324 |
+
*
|
1325 |
+
* @param resource &$curl CURL resource
|
1326 |
+
* @param string &$data Data
|
1327 |
+
* @return integer
|
1328 |
+
*/
|
1329 |
+
private function __responseWriteCallback(&$curl, &$data) {
|
1330 |
+
if ($this->response->code == 200 && $this->fp !== false)
|
1331 |
+
return fwrite($this->fp, $data);
|
1332 |
+
else
|
1333 |
+
$this->response->body .= $data;
|
1334 |
+
return strlen($data);
|
1335 |
+
}
|
1336 |
+
|
1337 |
+
|
1338 |
+
/**
|
1339 |
+
* CURL header callback
|
1340 |
+
*
|
1341 |
+
* @param resource &$curl CURL resource
|
1342 |
+
* @param string &$data Data
|
1343 |
+
* @return integer
|
1344 |
+
*/
|
1345 |
+
private function __responseHeaderCallback(&$curl, &$data) {
|
1346 |
+
if (($strlen = strlen($data)) <= 2) return $strlen;
|
1347 |
+
if (substr($data, 0, 4) == 'HTTP')
|
1348 |
+
$this->response->code = (int)substr($data, 9, 3);
|
1349 |
+
else {
|
1350 |
+
list($header, $value) = explode(': ', trim($data), 2);
|
1351 |
+
if ($header == 'Last-Modified')
|
1352 |
+
$this->response->headers['time'] = strtotime($value);
|
1353 |
+
elseif ($header == 'Content-Length')
|
1354 |
+
$this->response->headers['size'] = (int)$value;
|
1355 |
+
elseif ($header == 'Content-Type')
|
1356 |
+
$this->response->headers['type'] = $value;
|
1357 |
+
elseif ($header == 'ETag')
|
1358 |
+
$this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
|
1359 |
+
elseif (preg_match('/^x-amz-meta-.*$/', $header))
|
1360 |
+
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
|
1361 |
+
}
|
1362 |
+
return $strlen;
|
1363 |
+
}
|
1364 |
+
|
1365 |
+
}
|
app/options-backups.php
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?PHP
|
2 |
+
// don't load directly
|
3 |
+
if ( !defined('ABSPATH') )
|
4 |
+
die('-1');
|
5 |
+
|
6 |
+
//get GET data
|
7 |
+
if (isset($_GET['paged'])) $paged=$_GET['paged'];
|
8 |
+
|
9 |
+
//Get Backup files
|
10 |
+
$backups=backwpup_get_backup_files();
|
11 |
+
|
12 |
+
//Page links
|
13 |
+
$per_page = 20;
|
14 |
+
|
15 |
+
$pagenum = isset( $paged ) ? absint( $paged ) : 0;
|
16 |
+
if ( empty($pagenum) )
|
17 |
+
$pagenum = 1;
|
18 |
+
|
19 |
+
$num_backups = count($backups);
|
20 |
+
$num_pages = ceil($num_backups / $per_page);
|
21 |
+
|
22 |
+
$page_links = paginate_links( array(
|
23 |
+
'base' => add_query_arg('paged', '%#%'),
|
24 |
+
'format' => '',
|
25 |
+
'prev_text' => __('«'),
|
26 |
+
'next_text' => __('»'),
|
27 |
+
'total' => $num_pages,
|
28 |
+
'current' => $pagenum
|
29 |
+
));
|
30 |
+
?>
|
31 |
+
<div class="wrap">
|
32 |
+
<div id="icon-tools" class="icon32"><br /></div>
|
33 |
+
<h2><?php _e("BackWPup Manage Backups", "backwpup"); ?></h2>
|
34 |
+
<ul class="subsubsub">
|
35 |
+
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
36 |
+
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
37 |
+
<li><a href="admin.php?page=BackWPup&action=backups" class="current"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
38 |
+
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
39 |
+
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
40 |
+
</ul>
|
41 |
+
|
42 |
+
<form id="logs-filter" action="" method="post">
|
43 |
+
<?php wp_nonce_field('actions-backups'); ?>
|
44 |
+
<input type="hidden" name="page" value="BackWPup" />
|
45 |
+
<div class="tablenav">
|
46 |
+
|
47 |
+
<div class="alignleft actions">
|
48 |
+
<select name="action" class="select-action">
|
49 |
+
<option value="backups" selected="selected"><?PHP _e('Bulk Actions','backwpup'); ?></option>
|
50 |
+
<option value="delete-backup"><?PHP _e('Delete','backwpup'); ?></option>
|
51 |
+
</select>
|
52 |
+
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction" id="doaction" class="button-secondary action" />
|
53 |
+
</div>
|
54 |
+
|
55 |
+
<?php if ( $page_links ) { ?>
|
56 |
+
<div class="tablenav-pages"><?php $page_links_text = sprintf( '<span class="displaying-num">' . __( 'Displaying %s–%s of %s' ) . '</span>%s',
|
57 |
+
number_format_i18n( ( $pagenum - 1 ) * $per_page + 1 ),
|
58 |
+
number_format_i18n( min( $pagenum * $per_page, $num_backups ) ),
|
59 |
+
number_format_i18n( $num_backups ),
|
60 |
+
$page_links
|
61 |
+
); echo $page_links_text; ?></div>
|
62 |
+
<?php } ?>
|
63 |
+
<div class="clear"></div>
|
64 |
+
</div>
|
65 |
+
|
66 |
+
<div class="clear"></div>
|
67 |
+
|
68 |
+
<table class="widefat" cellspacing="0">
|
69 |
+
<thead>
|
70 |
+
<tr>
|
71 |
+
<?php print_column_headers($page_hook); ?>
|
72 |
+
</tr>
|
73 |
+
</thead>
|
74 |
+
|
75 |
+
<tfoot>
|
76 |
+
<tr>
|
77 |
+
<?php print_column_headers($page_hook, false); ?>
|
78 |
+
</tr>
|
79 |
+
</tfoot>
|
80 |
+
|
81 |
+
<tbody id="the-list" class="list:post">
|
82 |
+
|
83 |
+
<?php
|
84 |
+
$item_columns = get_column_headers($page_hook);
|
85 |
+
$hidden = get_hidden_columns($page_hook);
|
86 |
+
$jobs=get_option('backwpup_jobs'); //Load jobs
|
87 |
+
|
88 |
+
foreach ($backups as $backupnum => $backup) {
|
89 |
+
if (!($backupnum>=($pagenum*$per_page-$per_page) and $backupnum<($pagenum*$per_page)))
|
90 |
+
continue;
|
91 |
+
$jobvalue=backwpup_check_job_vars($jobs[$backup['jobid']]); //Check job values
|
92 |
+
?><tr id="<?PHP echo $logfile?>" valign="top"><?PHP
|
93 |
+
foreach($item_columns as $column_name=>$column_display_name) {
|
94 |
+
$class = "class=\"column-$column_name\"";
|
95 |
+
|
96 |
+
$style = '';
|
97 |
+
if ( in_array($column_name, $hidden) )
|
98 |
+
$style = ' style="display:none;"';
|
99 |
+
|
100 |
+
$attributes = "$class$style";
|
101 |
+
|
102 |
+
switch($column_name) {
|
103 |
+
case 'cb':
|
104 |
+
echo '<th scope="row" class="check-column"><input type="checkbox" name="backupfiles[]" value="'. esc_attr($backup['file'].':'.$backup['jobid'].':'.$backup['type']) .'" /></th>';
|
105 |
+
break;
|
106 |
+
case 'id':
|
107 |
+
echo "<td $attributes>".$backup['jobid']."</td>";
|
108 |
+
break;
|
109 |
+
case 'backup':
|
110 |
+
if ($backup['type']=='FOLDER') {
|
111 |
+
echo "<td $attributes><strong>".basename($backup['file'])."</strong><br />".dirname($backup['file'])."/";
|
112 |
+
} elseif ($backup['type']=='S3') {
|
113 |
+
echo "<td $attributes><strong>".basename($backup['file'])."</strong><br />S3://".$jobvalue['awsBucket']."/".dirname($backup['file'])."/";
|
114 |
+
} elseif ($backup['type']=='FTP') {
|
115 |
+
echo "<td $attributes><strong>".basename($backup['file'])."</strong><br />ftp://".$jobvalue['ftphost'].dirname($backup['file'])."/";
|
116 |
+
}
|
117 |
+
$actions = array();
|
118 |
+
$actions['delete'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=delete-backup&paged='.$paged.'&backupfile='.$backup['file'].'&jobid='.$backup['jobid'].'&type='.$backup['type'], 'delete-backup_'.basename($backup['file'])) . "\" onclick=\"if ( confirm('" . esc_js(__("You are about to delete this Backup Archive. \n 'Cancel' to stop, 'OK' to delete.","backwpup")) . "') ) { return true;}return false;\">" . __('Delete') . "</a>";
|
119 |
+
$actions['download'] = "<a class=\"submitdelete\" href=\"" . $backup['downloadurl'] . "\">" . __('Download','backwpup') . "</a>";
|
120 |
+
$action_count = count($actions);
|
121 |
+
$i = 0;
|
122 |
+
echo '<br /><div class="row-actions">';
|
123 |
+
foreach ( $actions as $action => $linkaction ) {
|
124 |
+
++$i;
|
125 |
+
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
|
126 |
+
echo "<span class='$action'>$linkaction$sep</span>";
|
127 |
+
}
|
128 |
+
echo '</div>';
|
129 |
+
echo "</td>";
|
130 |
+
break;
|
131 |
+
case 'size':
|
132 |
+
echo "<td $attributes>";
|
133 |
+
if (!empty($backup['filesize']) and $backup['filesize']!=-1) {
|
134 |
+
echo backwpup_formatBytes($backup['filesize']);
|
135 |
+
} else {
|
136 |
+
_e('?','backwpup');
|
137 |
+
}
|
138 |
+
echo "</td>";
|
139 |
+
break;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
echo "\n </tr>\n";
|
143 |
+
}
|
144 |
+
?></tbody>
|
145 |
+
</table>
|
146 |
+
|
147 |
+
<div class="tablenav">
|
148 |
+
<div class="alignleft actions">
|
149 |
+
<select name="action2" class="select-action">
|
150 |
+
<option value="backups" selected="selected"><?PHP _e('Bulk Actions','backwpup'); ?></option>
|
151 |
+
<option value="delete-backup"><?PHP _e('Delete','backwpup'); ?></option>
|
152 |
+
</select>
|
153 |
+
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
|
154 |
+
</div>
|
155 |
+
|
156 |
+
<br class="clear" />
|
157 |
+
<?php
|
158 |
+
if ( $page_links )
|
159 |
+
echo "<div class='tablenav-pages'>$page_links_text</div>";
|
160 |
+
?>
|
161 |
+
</div>
|
162 |
+
</form>
|
163 |
+
<br class="clear" />
|
164 |
+
|
165 |
+
</div>
|
app/options-logs.php
CHANGED
@@ -2,6 +2,40 @@
|
|
2 |
// don't load directly
|
3 |
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
?>
|
6 |
<div class="wrap">
|
7 |
<div id="icon-tools" class="icon32"><br /></div>
|
@@ -9,6 +43,7 @@ if ( !defined('ABSPATH') )
|
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs" class="current"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
12 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
14 |
</ul>
|
@@ -20,13 +55,21 @@ if ( !defined('ABSPATH') )
|
|
20 |
|
21 |
<div class="alignleft actions">
|
22 |
<select name="action" class="select-action">
|
23 |
-
<option value="
|
24 |
<option value="delete-logs"><?PHP _e('Delete','backwpup'); ?></option>
|
25 |
</select>
|
26 |
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction" id="doaction" class="button-secondary action" />
|
27 |
</div>
|
28 |
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
31 |
|
32 |
<div class="clear"></div>
|
@@ -50,19 +93,9 @@ if ( !defined('ABSPATH') )
|
|
50 |
$item_columns = get_column_headers($page_hook);
|
51 |
$hidden = get_hidden_columns($page_hook);
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
while (($file = readdir( $dir ) ) !== false ) {
|
57 |
-
if (is_file($cfg['dirlogs'].'/'.$file) and 'backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and '.html' == substr($file,-5))
|
58 |
-
$logfiles[]=$file;
|
59 |
-
}
|
60 |
-
closedir( $dir );
|
61 |
-
rsort($logfiles);
|
62 |
-
}
|
63 |
-
|
64 |
-
|
65 |
-
foreach ($logfiles as $logfile) {
|
66 |
$logdata=backwpup_read_logheader($cfg['dirlogs'].'/'.$logfile);
|
67 |
?><tr id="<?PHP echo $logfile?>" valign="top"><?PHP
|
68 |
foreach($item_columns as $column_name=>$column_display_name) {
|
@@ -94,10 +127,8 @@ if ( !defined('ABSPATH') )
|
|
94 |
echo "<td $attributes><strong><a href=\"".wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile)."\" title=\"".__('View log','backwpup')."\">".date_i18n(get_option('date_format'),$logdata['logtime'])." ".date_i18n(get_option('time_format'),$logdata['logtime']).": <i>".$logdata['name']."</i></a></strong>";
|
95 |
$actions = array();
|
96 |
$actions['view'] = "<a href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile) . "\">" . __('View','backwpup') . "</a>";
|
97 |
-
$actions['delete'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=delete-logs&logfile='.$logfile, 'delete-log_'.$logfile) . "\" onclick=\"if ( confirm('" . esc_js(__("You are about to delete this Job. \n 'Cancel' to stop, 'OK' to delete.","backwpup")) . "') ) { return true;}return false;\">" . __('Delete') . "</a>";
|
98 |
-
$actions['
|
99 |
-
if (!empty($logdata['backupfile']) and is_file($logdata['backupfile']))
|
100 |
-
$actions['downloadbackup'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=download&file='.$logdata['backupfile'], 'download-backup_'.basename($logdata['backupfile'])) . "\">" . __('Download Backup','backwpup') . "</a>";
|
101 |
$action_count = count($actions);
|
102 |
$i = 0;
|
103 |
echo '<br /><div class="row-actions">';
|
@@ -123,10 +154,10 @@ if ( !defined('ABSPATH') )
|
|
123 |
break;
|
124 |
case 'size':
|
125 |
echo "<td $attributes>";
|
126 |
-
if (!empty($logdata['backupfile']) and
|
127 |
-
echo backwpup_formatBytes(
|
128 |
} elseif (!empty($logdata['backupfile'])) {
|
129 |
-
_e('
|
130 |
} else {
|
131 |
_e('only Log','backwpup');
|
132 |
}
|
@@ -147,13 +178,17 @@ if ( !defined('ABSPATH') )
|
|
147 |
<div class="tablenav">
|
148 |
<div class="alignleft actions">
|
149 |
<select name="action2" class="select-action">
|
150 |
-
<option value="
|
151 |
<option value="delete-logs"><?PHP _e('Delete','backwpup'); ?></option>
|
152 |
</select>
|
153 |
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
|
154 |
</div>
|
155 |
|
156 |
-
<br class="clear" />
|
|
|
|
|
|
|
|
|
157 |
</div>
|
158 |
</form>
|
159 |
<br class="clear" />
|
2 |
// don't load directly
|
3 |
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
+
|
6 |
+
//get GET data
|
7 |
+
if (isset($_GET['paged'])) $paged=$_GET['paged'];
|
8 |
+
|
9 |
+
//Get log files
|
10 |
+
$logfiles=array();
|
11 |
+
if ( $dir = @opendir( $cfg['dirlogs'] ) ) {
|
12 |
+
while (($file = readdir( $dir ) ) !== false ) {
|
13 |
+
if (is_file($cfg['dirlogs'].'/'.$file) and 'backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and '.html' == substr($file,-5))
|
14 |
+
$logfiles[]=$file;
|
15 |
+
}
|
16 |
+
closedir( $dir );
|
17 |
+
rsort($logfiles);
|
18 |
+
}
|
19 |
+
|
20 |
+
//Page links
|
21 |
+
$per_page = 20;
|
22 |
+
|
23 |
+
$pagenum = isset( $paged ) ? absint( $paged ) : 0;
|
24 |
+
if ( empty($pagenum) )
|
25 |
+
$pagenum = 1;
|
26 |
+
|
27 |
+
$num_logs = count($logfiles);
|
28 |
+
$num_pages = ceil($num_logs / $per_page);
|
29 |
+
|
30 |
+
$page_links = paginate_links( array(
|
31 |
+
'base' => add_query_arg('paged', '%#%'),
|
32 |
+
'format' => '',
|
33 |
+
'prev_text' => __('«'),
|
34 |
+
'next_text' => __('»'),
|
35 |
+
'total' => $num_pages,
|
36 |
+
'current' => $pagenum
|
37 |
+
));
|
38 |
+
|
39 |
?>
|
40 |
<div class="wrap">
|
41 |
<div id="icon-tools" class="icon32"><br /></div>
|
43 |
<ul class="subsubsub">
|
44 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
45 |
<li><a href="admin.php?page=BackWPup&action=logs" class="current"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
46 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
47 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
48 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
49 |
</ul>
|
55 |
|
56 |
<div class="alignleft actions">
|
57 |
<select name="action" class="select-action">
|
58 |
+
<option value="logs" selected="selected"><?PHP _e('Bulk Actions','backwpup'); ?></option>
|
59 |
<option value="delete-logs"><?PHP _e('Delete','backwpup'); ?></option>
|
60 |
</select>
|
61 |
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction" id="doaction" class="button-secondary action" />
|
62 |
</div>
|
63 |
|
64 |
+
<?php if ( $page_links ) { ?>
|
65 |
+
<div class="tablenav-pages"><?php $page_links_text = sprintf( '<span class="displaying-num">' . __( 'Displaying %s–%s of %s' ) . '</span>%s',
|
66 |
+
number_format_i18n( ( $pagenum - 1 ) * $per_page + 1 ),
|
67 |
+
number_format_i18n( min( $pagenum * $per_page, $num_logs ) ),
|
68 |
+
number_format_i18n( $num_logs ),
|
69 |
+
$page_links
|
70 |
+
); echo $page_links_text; ?></div>
|
71 |
+
<?php } ?>
|
72 |
+
<div class="clear"></div>
|
73 |
</div>
|
74 |
|
75 |
<div class="clear"></div>
|
93 |
$item_columns = get_column_headers($page_hook);
|
94 |
$hidden = get_hidden_columns($page_hook);
|
95 |
|
96 |
+
foreach ($logfiles as $lognum => $logfile) {
|
97 |
+
if (!($lognum>=($pagenum*$per_page-$per_page) and $lognum<($pagenum*$per_page)))
|
98 |
+
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
$logdata=backwpup_read_logheader($cfg['dirlogs'].'/'.$logfile);
|
100 |
?><tr id="<?PHP echo $logfile?>" valign="top"><?PHP
|
101 |
foreach($item_columns as $column_name=>$column_display_name) {
|
127 |
echo "<td $attributes><strong><a href=\"".wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile)."\" title=\"".__('View log','backwpup')."\">".date_i18n(get_option('date_format'),$logdata['logtime'])." ".date_i18n(get_option('time_format'),$logdata['logtime']).": <i>".$logdata['name']."</i></a></strong>";
|
128 |
$actions = array();
|
129 |
$actions['view'] = "<a href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=view_log&logfile='.$cfg['dirlogs'].'/'.$logfile, 'view-log_'.$logfile) . "\">" . __('View','backwpup') . "</a>";
|
130 |
+
$actions['delete'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=delete-logs&paged='.$paged.'&logfile='.$logfile, 'delete-log_'.$logfile) . "\" onclick=\"if ( confirm('" . esc_js(__("You are about to delete this Job. \n 'Cancel' to stop, 'OK' to delete.","backwpup")) . "') ) { return true;}return false;\">" . __('Delete') . "</a>";
|
131 |
+
$actions['download'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&action=download&file='.$cfg['dirlogs'].'/'.$logfile, 'download-backup_'.$logfile) . "\">" . __('Download','backwpup') . "</a>";
|
|
|
|
|
132 |
$action_count = count($actions);
|
133 |
$i = 0;
|
134 |
echo '<br /><div class="row-actions">';
|
154 |
break;
|
155 |
case 'size':
|
156 |
echo "<td $attributes>";
|
157 |
+
if (!empty($logdata['backupfile']) and !empty($logdata['backupfilesize'])) {
|
158 |
+
echo backwpup_formatBytes($logdata['backupfilesize']);
|
159 |
} elseif (!empty($logdata['backupfile'])) {
|
160 |
+
_e('?','backwpup');
|
161 |
} else {
|
162 |
_e('only Log','backwpup');
|
163 |
}
|
178 |
<div class="tablenav">
|
179 |
<div class="alignleft actions">
|
180 |
<select name="action2" class="select-action">
|
181 |
+
<option value="logs" selected="selected"><?PHP _e('Bulk Actions','backwpup'); ?></option>
|
182 |
<option value="delete-logs"><?PHP _e('Delete','backwpup'); ?></option>
|
183 |
</select>
|
184 |
<input type="submit" value="<?PHP _e('Apply','backwpup'); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
|
185 |
</div>
|
186 |
|
187 |
+
<br class="clear" />
|
188 |
+
<?php
|
189 |
+
if ( $page_links )
|
190 |
+
echo "<div class='tablenav-pages'>$page_links_text</div>";
|
191 |
+
?>
|
192 |
</div>
|
193 |
</form>
|
194 |
<br class="clear" />
|
app/options-runnow.php
CHANGED
@@ -9,6 +9,7 @@ if ( !defined('ABSPATH') )
|
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
12 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
14 |
</ul>
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
12 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
15 |
</ul>
|
app/options-save.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
|
6 |
-
if ($_REQUEST['action2']!='-1' and !empty($_REQUEST['doaction2']))
|
7 |
$_REQUEST['action']=$_REQUEST['action2'];
|
8 |
|
9 |
switch($_REQUEST['action']) {
|
@@ -49,6 +49,86 @@ case 'delete-logs': //Delete Log
|
|
49 |
}
|
50 |
$_REQUEST['action']='logs';
|
51 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
case 'savecfg': //Save config form Setings page
|
53 |
check_admin_referer('backwpup-cfg');
|
54 |
$cfg=get_option('backwpup'); //Load Settings
|
@@ -106,11 +186,34 @@ case 'download': //Download Backup
|
|
106 |
header("Content-Transfer-Encoding: binary");
|
107 |
header("Content-Length: ".filesize($_GET['file']));
|
108 |
@readfile($_GET['file']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
} else {
|
110 |
header('HTTP/1.0 404 Not Found');
|
111 |
die(__('File does not exist.', 'backwpup'));
|
112 |
}
|
113 |
-
$_REQUEST['action']='logs';
|
114 |
break;
|
115 |
case 'saveeditjob': //Save Job settings
|
116 |
$jobid = (int) $_POST['jobid'];
|
3 |
if ( !defined('ABSPATH') )
|
4 |
die('-1');
|
5 |
|
6 |
+
if ($_REQUEST['action2']!='backups' and $_REQUEST['action2']!='logs' and $_REQUEST['action2']!='-1' and !empty($_REQUEST['doaction2']))
|
7 |
$_REQUEST['action']=$_REQUEST['action2'];
|
8 |
|
9 |
switch($_REQUEST['action']) {
|
49 |
}
|
50 |
$_REQUEST['action']='logs';
|
51 |
break;
|
52 |
+
case 'delete-backup': //Delete Backup archives
|
53 |
+
$deletebackups=array();
|
54 |
+
if (is_Array($_POST['backupfiles'])) {
|
55 |
+
check_admin_referer('actions-backups');
|
56 |
+
$i=0;
|
57 |
+
foreach ($_POST['backupfiles'] as $backupfile) {
|
58 |
+
list($deletebackups[$i]['file'],$deletebackups[$i]['jobid'],$deletebackups[$i]['type'])=explode(':',$backupfile,3);
|
59 |
+
$i++;
|
60 |
+
}
|
61 |
+
} else {
|
62 |
+
check_admin_referer('delete-backup_' . basename($_GET['backupfile']));
|
63 |
+
$deletebackups[0]['type']=$_GET['type'];
|
64 |
+
$deletebackups[0]['jobid']=$_GET['jobid'];
|
65 |
+
$deletebackups[0]['file']=$_GET['backupfile'];
|
66 |
+
}
|
67 |
+
|
68 |
+
if(empty($deletebackups)) {
|
69 |
+
$_REQUEST['action']='backups';
|
70 |
+
break;
|
71 |
+
}
|
72 |
+
|
73 |
+
$jobs=get_option('backwpup_jobs'); //Load jobs
|
74 |
+
if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
|
75 |
+
if (!class_exists('S3'))
|
76 |
+
require_once(plugin_dir_path(__FILE__).'libs/S3.php');
|
77 |
+
}
|
78 |
+
|
79 |
+
$num=0;
|
80 |
+
foreach ($deletebackups as $backups) {
|
81 |
+
$jobvalue=backwpup_check_job_vars($jobs[$backups['jobid']]); //Check job values
|
82 |
+
if ($backups['type']=='FOLDER') {
|
83 |
+
if (is_file($backups['file']))
|
84 |
+
unlink($backups['file']);
|
85 |
+
} elseif ($backups['type']=='S3') {
|
86 |
+
if (class_exists('S3')) {
|
87 |
+
if (!empty($jobvalue['awsAccessKey']) and !empty($jobvalue['awsSecretKey']) and !empty($jobvalue['awsBucket'])) {
|
88 |
+
$s3 = new S3($jobvalue['awsAccessKey'], $jobvalue['awsSecretKey'], $jobvalue['awsSSL']);
|
89 |
+
$s3->deleteObject($jobvalue['awsBucket'],$backups['file']);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
} elseif ($backups['type']=='FTP') {
|
93 |
+
if (!empty($jobvalue['ftphost']) and !empty($jobvalue['ftpuser']) and !empty($jobvalue['ftppass'])) {
|
94 |
+
$ftpport=21;
|
95 |
+
$ftphost=$jobvalue['ftphost'];
|
96 |
+
if (false !== strpos($jobvalue['ftphost'],':')) //look for port
|
97 |
+
list($ftphost,$ftpport)=explode(':',$jobvalue,2);
|
98 |
+
|
99 |
+
$SSL=false;
|
100 |
+
if (function_exists('ftp_ssl_connect')) { //make SSL FTP connection
|
101 |
+
$ftp_conn_id = ftp_ssl_connect($ftphost,$ftpport,10);
|
102 |
+
if ($ftp_conn_id)
|
103 |
+
$SSL=true;
|
104 |
+
}
|
105 |
+
if (!$ftp_conn_id) { //make normal FTP conection if SSL not work
|
106 |
+
$ftp_conn_id = ftp_connect($ftphost,$ftpport,10);
|
107 |
+
}
|
108 |
+
if ($ftp_conn_id) {
|
109 |
+
//FTP Login
|
110 |
+
$loginok=false;
|
111 |
+
if (@ftp_login($ftp_conn_id, $jobvalue['ftpuser'], base64_decode($jobvalue['ftppass']))) {
|
112 |
+
$loginok=true;
|
113 |
+
} else { //if PHP ftp login don't work use raw login
|
114 |
+
if (substr(trim(ftp_raw($ftp_conn_id,'USER '.$jobvalue['ftpuser'])),0,3)<400) {
|
115 |
+
if (substr(trim(ftp_raw($ftp_conn_id,'PASS '.base64_decode($jobvalue['ftppass']))),0,3)<400) {
|
116 |
+
$loginok=true;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
121 |
+
if ($loginok) {
|
122 |
+
ftp_pasv($ftp_conn_id, true);
|
123 |
+
ftp_delete($ftp_conn_id, $backups['file']);
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
$num++;
|
128 |
+
}
|
129 |
+
$backwpup_message=$num.' '.__('Backup Archives deleted', 'backwpup');
|
130 |
+
$_REQUEST['action']='backups';
|
131 |
+
break;
|
132 |
case 'savecfg': //Save config form Setings page
|
133 |
check_admin_referer('backwpup-cfg');
|
134 |
$cfg=get_option('backwpup'); //Load Settings
|
186 |
header("Content-Transfer-Encoding: binary");
|
187 |
header("Content-Length: ".filesize($_GET['file']));
|
188 |
@readfile($_GET['file']);
|
189 |
+
die();
|
190 |
+
} else {
|
191 |
+
header('HTTP/1.0 404 Not Found');
|
192 |
+
die(__('File does not exist.', 'backwpup'));
|
193 |
+
}
|
194 |
+
break;
|
195 |
+
case 'downloads3': //Download S3 Backup
|
196 |
+
//check_admin_referer('download-backup_'.basename($_GET['file']));
|
197 |
+
require_once(plugin_dir_path(__FILE__).'libs/S3.php');
|
198 |
+
$jobs=get_option('backwpup_jobs');
|
199 |
+
$jobid=$_GET['jobid'];
|
200 |
+
$s3 = new S3($jobs[$jobid]['awsAccessKey'], $jobs[$jobid]['awsSecretKey'],$jobs[$jobid]['awsSSL']);
|
201 |
+
if ($contents = $s3->getObjectInfo($jobs[$jobid]['awsBucket'],$_GET['file'])) {
|
202 |
+
header("Pragma: public");
|
203 |
+
header("Expires: 0");
|
204 |
+
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
205 |
+
header("Content-Type: application/force-download");
|
206 |
+
header("Content-Type: application/octet-stream");
|
207 |
+
header("Content-Type: application/download");
|
208 |
+
header("Content-Disposition: attachment; filename=".basename($_GET['file']).";");
|
209 |
+
header("Content-Transfer-Encoding: binary");
|
210 |
+
//header("Content-Length: ".$contents['size']);
|
211 |
+
var_dump($s3->getObject($jobs[$jobid]['awsBucket'], $_GET['file']));
|
212 |
+
die();
|
213 |
} else {
|
214 |
header('HTTP/1.0 404 Not Found');
|
215 |
die(__('File does not exist.', 'backwpup'));
|
216 |
}
|
|
|
217 |
break;
|
218 |
case 'saveeditjob': //Save Job settings
|
219 |
$jobid = (int) $_POST['jobid'];
|
app/options-settings.php
CHANGED
@@ -9,6 +9,7 @@ if ( !defined('ABSPATH') )
|
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
12 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=settings" class="current"><?PHP _e('Settings','backwpup'); ?></a></li>
|
14 |
</ul>
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
12 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=settings" class="current"><?PHP _e('Settings','backwpup'); ?></a></li>
|
15 |
</ul>
|
app/options-tools.php
CHANGED
@@ -10,6 +10,7 @@ if ( !defined('ABSPATH') )
|
|
10 |
<ul class="subsubsub">
|
11 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
12 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
13 |
<li><a href="admin.php?page=BackWPup&action=tools" class="current"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
15 |
</ul>
|
10 |
<ul class="subsubsub">
|
11 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
12 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
13 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=tools" class="current"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
15 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
16 |
</ul>
|
app/options-view_log.php
CHANGED
@@ -9,6 +9,7 @@ if ( !defined('ABSPATH') )
|
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
12 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
14 |
</ul>
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
12 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
15 |
</ul>
|
app/options.php
CHANGED
@@ -9,6 +9,7 @@ if ( !defined('ABSPATH') )
|
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup" class="current"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
|
|
12 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
14 |
</ul>
|
9 |
<ul class="subsubsub">
|
10 |
<li><a href="admin.php?page=BackWPup" class="current"><?PHP _e('Jobs','backwpup'); ?></a> |</li>
|
11 |
<li><a href="admin.php?page=BackWPup&action=logs"><?PHP _e('Logs','backwpup'); ?></a> |</li>
|
12 |
+
<li><a href="admin.php?page=BackWPup&action=backups"><?PHP _e('Backups','backwpup'); ?></a> |</li>
|
13 |
<li><a href="admin.php?page=BackWPup&action=tools"><?PHP _e('Tools','backwpup'); ?></a> |</li>
|
14 |
<li><a href="admin.php?page=BackWPup&action=settings"><?PHP _e('Settings','backwpup'); ?></a></li>
|
15 |
</ul>
|
backwpup.php
CHANGED
@@ -1,57 +1,57 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Plugin Name: BackWPup
|
4 |
-
Plugin URI: http://danielhuesken.de/portfolio/backwpup/
|
5 |
-
Description: Backup and more of your WordPress Blog Database and Files.
|
6 |
-
Author: Daniel Hüsken
|
7 |
-
Version: 1.
|
8 |
-
Author URI: http://danielhuesken.de
|
9 |
-
Text Domain: backwpup
|
10 |
-
Domain Path: /lang/
|
11 |
-
*/
|
12 |
-
|
13 |
-
/*
|
14 |
-
Copyright 2009 Daniel H�sken (email : daniel@huesken-net.de)
|
15 |
-
|
16 |
-
This program is free software; you can redistribute it and/or modify
|
17 |
-
it under the terms of the GNU General Public License as published by
|
18 |
-
the Free Software Foundation; either version 2 of the License, or
|
19 |
-
(at your option) any later version.
|
20 |
-
|
21 |
-
This program is distributed in the hope that it will be useful,
|
22 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
23 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
24 |
-
GNU General Public License for more details.
|
25 |
-
|
26 |
-
You should have received a copy of the GNU General Public License
|
27 |
-
along with this program; if not, write to the Free Software
|
28 |
-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
29 |
-
*/
|
30 |
-
|
31 |
-
// don't load directly
|
32 |
-
if ( !defined('ABSPATH') )
|
33 |
-
die('-1');
|
34 |
-
|
35 |
-
//Set plugin dirname
|
36 |
-
define('BACKWPUP_PLUGIN_BASEDIR', dirname(plugin_basename(__FILE__)));
|
37 |
-
//Set Plugin Version
|
38 |
-
define('BACKWPUP_VERSION', '1.
|
39 |
-
//load Text Domain
|
40 |
-
load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_BASEDIR.'/lang');
|
41 |
-
//Load functions file
|
42 |
-
require_once(plugin_dir_path(__FILE__).'app/functions.php');
|
43 |
-
//Plugin activate
|
44 |
-
register_activation_hook(__FILE__, 'backwpup_plugin_activate');
|
45 |
-
//Plugin deactivate
|
46 |
-
register_deactivation_hook(__FILE__, 'backwpup_plugin_deactivate');
|
47 |
-
//Plugin uninstall
|
48 |
-
register_uninstall_hook(__FILE__, 'backwpup_plugin_uninstall');
|
49 |
-
|
50 |
-
//Version check
|
51 |
-
if (version_compare($wp_version, '2.8', '<') and version_compare(phpversion(), '5.0.0', '<')) { // Let only Activate on WordPress Version 2.8 or
|
52 |
-
add_action('admin_notices', create_function('', 'echo \'<div id="message" class="error fade"><p><strong>' . __('Sorry, BackWPup works only with WordPress 2.8 and PHP 5.0.0 or
|
53 |
-
} else {
|
54 |
-
//Plugin init
|
55 |
-
add_action('plugins_loaded', 'backwpup_init');
|
56 |
-
}
|
57 |
-
?>
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: BackWPup
|
4 |
+
Plugin URI: http://danielhuesken.de/portfolio/backwpup/
|
5 |
+
Description: Backup and more of your WordPress Blog Database and Files.
|
6 |
+
Author: Daniel Hüsken
|
7 |
+
Version: 1.2.0
|
8 |
+
Author URI: http://danielhuesken.de
|
9 |
+
Text Domain: backwpup
|
10 |
+
Domain Path: /lang/
|
11 |
+
*/
|
12 |
+
|
13 |
+
/*
|
14 |
+
Copyright 2009 Daniel H�sken (email : daniel@huesken-net.de)
|
15 |
+
|
16 |
+
This program is free software; you can redistribute it and/or modify
|
17 |
+
it under the terms of the GNU General Public License as published by
|
18 |
+
the Free Software Foundation; either version 2 of the License, or
|
19 |
+
(at your option) any later version.
|
20 |
+
|
21 |
+
This program is distributed in the hope that it will be useful,
|
22 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
23 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
24 |
+
GNU General Public License for more details.
|
25 |
+
|
26 |
+
You should have received a copy of the GNU General Public License
|
27 |
+
along with this program; if not, write to the Free Software
|
28 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
29 |
+
*/
|
30 |
+
|
31 |
+
// don't load directly
|
32 |
+
if ( !defined('ABSPATH') )
|
33 |
+
die('-1');
|
34 |
+
|
35 |
+
//Set plugin dirname
|
36 |
+
define('BACKWPUP_PLUGIN_BASEDIR', dirname(plugin_basename(__FILE__)));
|
37 |
+
//Set Plugin Version
|
38 |
+
define('BACKWPUP_VERSION', '1.2.0');
|
39 |
+
//load Text Domain
|
40 |
+
load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_BASEDIR.'/lang');
|
41 |
+
//Load functions file
|
42 |
+
require_once(plugin_dir_path(__FILE__).'app/functions.php');
|
43 |
+
//Plugin activate
|
44 |
+
register_activation_hook(__FILE__, 'backwpup_plugin_activate');
|
45 |
+
//Plugin deactivate
|
46 |
+
register_deactivation_hook(__FILE__, 'backwpup_plugin_deactivate');
|
47 |
+
//Plugin uninstall
|
48 |
+
register_uninstall_hook(__FILE__, 'backwpup_plugin_uninstall');
|
49 |
+
|
50 |
+
//Version check
|
51 |
+
if (version_compare($wp_version, '2.8', '<') and version_compare(phpversion(), '5.0.0', '<')) { // Let only Activate on WordPress Version 2.8 or higher
|
52 |
+
add_action('admin_notices', create_function('', 'echo \'<div id="message" class="error fade"><p><strong>' . __('Sorry, BackWPup works only with WordPress 2.8 and PHP 5.0.0 or higher!!!','backwpup') . '</strong></p></div>\';'));
|
53 |
+
} else {
|
54 |
+
//Plugin init
|
55 |
+
add_action('plugins_loaded', 'backwpup_init');
|
56 |
+
}
|
57 |
+
?>
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=danie
|
|
4 |
Tags: backup, admin, file, Database, mysql, cron, ftp, S3, export
|
5 |
Requires at least: 2.8
|
6 |
Tested up to: 3.0.0
|
7 |
-
Stable tag: 1.
|
8 |
|
9 |
Backup and more of your WordPress Blog Database and Files
|
10 |
|
@@ -13,11 +13,11 @@ Backup and more of your WordPress Blog Database and Files
|
|
13 |
Backup and more your Blog.
|
14 |
|
15 |
* Database Backup
|
16 |
-
*
|
17 |
* Optimize Database
|
18 |
* Check\Repair Database
|
19 |
* File Backup
|
20 |
-
* Backups in zip,tar,tar.gz,tar.bz2
|
21 |
* Store backup to Folder
|
22 |
* Store backup to FTP Server
|
23 |
* Store backup to Amazon S3
|
@@ -31,12 +31,12 @@ I can give no WARRANTY to any backups...
|
|
31 |
|
32 |
1. Download BackWPup Plugin.
|
33 |
1. Decompress and upload the contents of the archive into /wp-content/plugins/.
|
34 |
-
1. Activate the
|
35 |
|
36 |
== Frequently Asked Questions ==
|
37 |
= Requires =
|
38 |
* PHP 5.0.0
|
39 |
-
*
|
40 |
* curl (for Amazon S3 Support)
|
41 |
* gzip (for PCLZIP and gzip archives)
|
42 |
* bzip2 (for bzip2 archives)
|
@@ -44,54 +44,61 @@ I can give no WARRANTY to any backups...
|
|
44 |
= Where is the Database dump File =
|
45 |
in the root folder of the Archive. <i>DBName</i>.sql
|
46 |
|
47 |
-
= Where is the
|
48 |
in the root folder of the Archive. wordpress.<i>jjjj-mm-dd</i>.xml
|
49 |
|
50 |
= Zip File Support =
|
51 |
-
Plugin use PCLZIP lib if not
|
52 |
|
53 |
-
=
|
54 |
Supported Plugins
|
55 |
* maintenance-mode
|
56 |
* wp-maintenance-mode
|
57 |
-
*
|
58 |
|
59 |
-
if your
|
60 |
|
61 |
-
=
|
62 |
-
Copy the <i>DBName</i>.sql in the root folder of the
|
63 |
-
You
|
64 |
|
65 |
= Abnormal Script aborts =
|
66 |
-
Webserver
|
67 |
-
PHP
|
68 |
|
69 |
= Memory usage =
|
70 |
* The Plugin is coded to use low memory
|
71 |
-
* The Plugin will try to increase Memory
|
72 |
-
* PCLZIP lib need 8MB free
|
73 |
* Mail a archive need many Memory
|
74 |
|
75 |
-
= Mail
|
76 |
I have build in many options to Optimize the Mailing but the mailing lib uses high Memory.
|
77 |
-
|
78 |
|
79 |
== Screenshots ==
|
80 |
|
81 |
1. Job Page
|
82 |
|
83 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
= 1.1.1 =
|
85 |
* fixed S3 lib not found bug again.
|
86 |
* improved reschedule on activation problem.
|
87 |
|
88 |
= 1.1.0 =
|
89 |
-
* added
|
90 |
-
* added no
|
91 |
-
* changed error handling a bit and remove PHP errors that can't
|
92 |
-
* fixed problem with not compiled --enable-memory-limit in
|
93 |
* removed setting for memory limit use WP filter and default now (256M)
|
94 |
-
* now a time limit of 5 mins is set again for job execution but it will be
|
95 |
* added a shutdown function if __destruct not called for job
|
96 |
* added more flexible Backup file selection
|
97 |
|
@@ -99,11 +106,11 @@ Pleace mail only littele archives
|
|
99 |
* fix "Undefined index: dbshortinsert"
|
100 |
|
101 |
= 1.0.9 =
|
102 |
-
* change s3 class to hide
|
103 |
-
* add option to make MySQL INSERTs shorter (
|
104 |
-
* add
|
105 |
-
*
|
106 |
-
* add S3
|
107 |
|
108 |
= 1.0.8 =
|
109 |
* fix temp backup file not deleted if no destination folder
|
@@ -124,42 +131,42 @@ Pleace mail only littele archives
|
|
124 |
|
125 |
= 1.0.4 =
|
126 |
* fixed bugs in DB restore
|
127 |
-
* use WP functions to get
|
128 |
|
129 |
= 1.0.3 =
|
130 |
-
*
|
131 |
|
132 |
= 1.0.2 =
|
133 |
-
*
|
134 |
|
135 |
= 1.0.1 =
|
136 |
-
*
|
137 |
|
138 |
= 1.0.0 =
|
139 |
-
* now
|
140 |
* new backup files formats tar, tar.gz, tar.bz2
|
141 |
* all job types can made in one job
|
142 |
-
* added
|
143 |
* removed PclZip trace code
|
144 |
* fixed time display and schedule bugs
|
145 |
* added some security
|
146 |
-
*
|
147 |
* new Design on some Pages
|
148 |
|
149 |
= 0.8.1 =
|
150 |
-
* use global var
|
151 |
-
*
|
152 |
|
153 |
= 0.8.0 =
|
154 |
-
*
|
155 |
-
* crate .htaccsses on Apache and index.html on other
|
156 |
* fixed global for $wp_version
|
157 |
-
* set max execution time to 0 for
|
158 |
* use WP function to generate options tables
|
159 |
* Backup file list and zip creation changes
|
160 |
* Added support for Amazon S3
|
161 |
* Only works with PHP 5 now
|
162 |
-
*
|
163 |
* PHP errors now in Backup log
|
164 |
* Log now in files
|
165 |
|
@@ -169,15 +176,15 @@ Pleace mail only littele archives
|
|
169 |
* make date with date_i18n
|
170 |
|
171 |
= 0.7.1 =
|
172 |
-
* FTP
|
173 |
* no Errors in Log for FTP ALLO command.
|
174 |
|
175 |
= 0.7.0 =
|
176 |
* set ftp Connection timeout to 10 sec
|
177 |
* fix bug for DB tables exclude
|
178 |
-
* DB Backup in
|
179 |
* Fixed missing ; in DB Backup
|
180 |
-
* Added tool DB Restore with automatic Blog
|
181 |
|
182 |
= 0.6.5 =
|
183 |
* Prevent direct file loading
|
@@ -197,7 +204,7 @@ Pleace mail only littele archives
|
|
197 |
* use ftp_row for login and other commands
|
198 |
* Add option to send only email on errors
|
199 |
* Internal structure changes
|
200 |
-
* Add option to disable WP-Cron and use
|
201 |
* bug fixes
|
202 |
|
203 |
= 0.6.2 =
|
4 |
Tags: backup, admin, file, Database, mysql, cron, ftp, S3, export
|
5 |
Requires at least: 2.8
|
6 |
Tested up to: 3.0.0
|
7 |
+
Stable tag: 1.2.0
|
8 |
|
9 |
Backup and more of your WordPress Blog Database and Files
|
10 |
|
13 |
Backup and more your Blog.
|
14 |
|
15 |
* Database Backup
|
16 |
+
* WordPress XML Export
|
17 |
* Optimize Database
|
18 |
* Check\Repair Database
|
19 |
* File Backup
|
20 |
+
* Backups in zip,tar,tar.gz,tar.bz2 format
|
21 |
* Store backup to Folder
|
22 |
* Store backup to FTP Server
|
23 |
* Store backup to Amazon S3
|
31 |
|
32 |
1. Download BackWPup Plugin.
|
33 |
1. Decompress and upload the contents of the archive into /wp-content/plugins/.
|
34 |
+
1. Activate the Plugin through the 'Plugins' menu in WordPress
|
35 |
|
36 |
== Frequently Asked Questions ==
|
37 |
= Requires =
|
38 |
* PHP 5.0.0
|
39 |
+
* WordPress 2.8
|
40 |
* curl (for Amazon S3 Support)
|
41 |
* gzip (for PCLZIP and gzip archives)
|
42 |
* bzip2 (for bzip2 archives)
|
44 |
= Where is the Database dump File =
|
45 |
in the root folder of the Archive. <i>DBName</i>.sql
|
46 |
|
47 |
+
= Where is the WordPress Export File =
|
48 |
in the root folder of the Archive. wordpress.<i>jjjj-mm-dd</i>.xml
|
49 |
|
50 |
= Zip File Support =
|
51 |
+
Plugin use PCLZIP lib if not PHP uses zip extension
|
52 |
|
53 |
+
= Maintenance Mode =
|
54 |
Supported Plugins
|
55 |
* maintenance-mode
|
56 |
* wp-maintenance-mode
|
57 |
+
* WordPress .maintenance file
|
58 |
|
59 |
+
if your Blog do not come back from Maintenance Mode switch back from Maintenance Mode by changing the Plugin options or delete the <i>.maintenance</i> file in Blog root folder.
|
60 |
|
61 |
+
= Restore a Blog Database =
|
62 |
+
Copy the <i>DBName</i>.sql in the root folder of the Blog and go to the tools tab in the Plugin.
|
63 |
+
You can use PHPMyAdmin also.
|
64 |
|
65 |
= Abnormal Script aborts =
|
66 |
+
Webserver normally abort Scrips that works longer then 300s.
|
67 |
+
PHP normally abort Script that works longer then 30s but the Plugin try too switch off the abortion.
|
68 |
|
69 |
= Memory usage =
|
70 |
* The Plugin is coded to use low memory
|
71 |
+
* The Plugin will try to increase Memory automatically if needed
|
72 |
+
* PCLZIP lib need 8MB free Memory for zipping
|
73 |
* Mail a archive need many Memory
|
74 |
|
75 |
+
= Mail archives =
|
76 |
I have build in many options to Optimize the Mailing but the mailing lib uses high Memory.
|
77 |
+
Place mail only little archives
|
78 |
|
79 |
== Screenshots ==
|
80 |
|
81 |
1. Job Page
|
82 |
|
83 |
== Changelog ==
|
84 |
+
= 1.2.0 =
|
85 |
+
* Backup file size now in log file
|
86 |
+
* Paged Logs Table
|
87 |
+
* added Backup Archives Page
|
88 |
+
* Grammar fixes
|
89 |
+
* Bug fixes
|
90 |
+
|
91 |
= 1.1.1 =
|
92 |
* fixed S3 lib not found bug again.
|
93 |
* improved reschedule on activation problem.
|
94 |
|
95 |
= 1.1.0 =
|
96 |
+
* added function to check/update job settings
|
97 |
+
* added no Ajax bucket list to job page
|
98 |
+
* changed error handling a bit and remove PHP errors that can't handled
|
99 |
+
* fixed problem with not compiled --enable-memory-limit in PHP
|
100 |
* removed setting for memory limit use WP filter and default now (256M)
|
101 |
+
* now a time limit of 5 mins. is set again for job execution but it will be reseted on every message. (prevent never ending jobs.)
|
102 |
* added a shutdown function if __destruct not called for job
|
103 |
* added more flexible Backup file selection
|
104 |
|
106 |
* fix "Undefined index: dbshortinsert"
|
107 |
|
108 |
= 1.0.9 =
|
109 |
+
* change s3 class to hide warnings
|
110 |
+
* add option to make MySQL INSERTs shorter (smaller dump file size.)
|
111 |
+
* add requirements checks
|
112 |
+
* Ajaxed S3 bucket selection in job settings
|
113 |
+
* add S3 Bucket can made in job settings
|
114 |
|
115 |
= 1.0.8 =
|
116 |
* fix temp backup file not deleted if no destination folder
|
131 |
|
132 |
= 1.0.4 =
|
133 |
* fixed bugs in DB restore
|
134 |
+
* use WP functions to get Plugin dirs
|
135 |
|
136 |
= 1.0.3 =
|
137 |
+
* hopefully fixed a cache problem on run now
|
138 |
|
139 |
= 1.0.2 =
|
140 |
+
* fixed bug for file excludes
|
141 |
|
142 |
= 1.0.1 =
|
143 |
+
* fixed bug for https
|
144 |
|
145 |
= 1.0.0 =
|
146 |
+
* now WordPress Exports to XML can made
|
147 |
* new backup files formats tar, tar.gz, tar.bz2
|
148 |
* all job types can made in one job
|
149 |
+
* added PHP zip extension support (use pclzip only if not supported)
|
150 |
* removed PclZip trace code
|
151 |
* fixed time display and schedule bugs
|
152 |
* added some security
|
153 |
+
* Maintenance Mode on MySQL Operations
|
154 |
* new Design on some Pages
|
155 |
|
156 |
= 0.8.1 =
|
157 |
+
* use global var instead of constant for log file
|
158 |
+
* PCLZip Trace included with setting for log Level
|
159 |
|
160 |
= 0.8.0 =
|
161 |
+
* Fixed not working default settings on settings page
|
162 |
+
* crate .htaccsses on Apache and index.html on other Webserver
|
163 |
* fixed global for $wp_version
|
164 |
+
* set max execution time to 0 for unlimited
|
165 |
* use WP function to generate options tables
|
166 |
* Backup file list and zip creation changes
|
167 |
* Added support for Amazon S3
|
168 |
* Only works with PHP 5 now
|
169 |
+
* Complete rewrite of job doing as PHP5 class
|
170 |
* PHP errors now in Backup log
|
171 |
* Log now in files
|
172 |
|
176 |
* make date with date_i18n
|
177 |
|
178 |
= 0.7.1 =
|
179 |
+
* FTP Connection test changes
|
180 |
* no Errors in Log for FTP ALLO command.
|
181 |
|
182 |
= 0.7.0 =
|
183 |
* set ftp Connection timeout to 10 sec
|
184 |
* fix bug for DB tables exclude
|
185 |
+
* DB Backup in MySQL Client encoding now
|
186 |
* Fixed missing ; in DB Backup
|
187 |
+
* Added tool DB Restore with automatic Blog URL/Path change
|
188 |
|
189 |
= 0.6.5 =
|
190 |
* Prevent direct file loading
|
204 |
* use ftp_row for login and other commands
|
205 |
* Add option to send only email on errors
|
206 |
* Internal structure changes
|
207 |
+
* Add option to disable WP-Cron and use Hosters cron
|
208 |
* bug fixes
|
209 |
|
210 |
= 0.6.2 =
|