Version Description
- 12/06/2012 =
- Updated to latest S3.php library with chunked uploading patch (for future improvements)
Download this release
Release Info
Developer | DavidAnderson |
Plugin | UpdraftPlus WordPress Backup Plugin |
Version | 0.9.12 |
Comparing to | |
See all releases |
Code changes from version 0.9.11 to 0.9.12
- includes/S3.php +180 -3
- readme.txt +3 -3
- updraftplus.php +2 -2
includes/S3.php
CHANGED
@@ -3,6 +3,7 @@
|
|
3 |
* $Id$
|
4 |
*
|
5 |
* Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
|
|
|
6 |
*
|
7 |
* Redistribution and use in source and binary forms, with or without
|
8 |
* modification, are permitted provided that the following conditions are met:
|
@@ -453,6 +454,180 @@ class S3
|
|
453 |
return $input;
|
454 |
}
|
455 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
456 |
|
457 |
/**
|
458 |
* Put an object
|
@@ -1794,8 +1969,10 @@ final class S3Request
|
|
1794 |
if (array_key_exists('acl', $this->parameters) ||
|
1795 |
array_key_exists('location', $this->parameters) ||
|
1796 |
array_key_exists('torrent', $this->parameters) ||
|
1797 |
-
array_key_exists('
|
1798 |
-
array_key_exists('
|
|
|
|
|
1799 |
$this->resource .= $query;
|
1800 |
}
|
1801 |
$url = (S3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
|
@@ -1874,7 +2051,7 @@ final class S3Request
|
|
1874 |
switch ($this->verb)
|
1875 |
{
|
1876 |
case 'GET': break;
|
1877 |
-
case 'PUT': case 'POST':
|
1878 |
if ($this->fp !== false)
|
1879 |
{
|
1880 |
curl_setopt($curl, CURLOPT_PUT, true);
|
3 |
* $Id$
|
4 |
*
|
5 |
* Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
|
6 |
+
* Portions copyright (c) 2012, David Anderson (http://www.simbahosting.co.uk). All rights reserved.
|
7 |
*
|
8 |
* Redistribution and use in source and binary forms, with or without
|
9 |
* modification, are permitted provided that the following conditions are met:
|
454 |
return $input;
|
455 |
}
|
456 |
|
457 |
+
/**
|
458 |
+
* Initiate a multi-part upload (http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html)
|
459 |
+
*
|
460 |
+
* @param string $bucket Bucket name
|
461 |
+
* @param string $uri Object URI
|
462 |
+
* @param constant $acl ACL constant
|
463 |
+
* @param array $metaHeaders Array of x-amz-meta-* headers
|
464 |
+
* @param array $requestHeaders Array of request headers or content type as a string
|
465 |
+
* @param constant $storageClass Storage class constant
|
466 |
+
* @return string | false
|
467 |
+
*/
|
468 |
+
|
469 |
+
public static function initiateMultipartUpload ($bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
|
470 |
+
{
|
471 |
+
|
472 |
+
$rest = new S3Request('POST', $bucket, $uri, self::$endpoint);
|
473 |
+
$rest->setParameter('uploads','');
|
474 |
+
|
475 |
+
// Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
|
476 |
+
if (is_array($requestHeaders))
|
477 |
+
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
|
478 |
+
|
479 |
+
// Set storage class
|
480 |
+
if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
|
481 |
+
$rest->setAmzHeader('x-amz-storage-class', $storageClass);
|
482 |
+
|
483 |
+
// Set ACL headers
|
484 |
+
$rest->setAmzHeader('x-amz-acl', $acl);
|
485 |
+
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
|
486 |
+
|
487 |
+
// Carry out the HTTP operation
|
488 |
+
$rest->getResponse();
|
489 |
+
|
490 |
+
if ($rest->response->error === false && $rest->response->code !== 200)
|
491 |
+
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
|
492 |
+
if ($rest->response->error !== false)
|
493 |
+
{
|
494 |
+
self::__triggerError(sprintf("S3::initiateMultipartUpload(): [%s] %s",
|
495 |
+
$rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
|
496 |
+
return false;
|
497 |
+
} elseif (isset($rest->response->body))
|
498 |
+
{
|
499 |
+
$body = new SimpleXMLElement($rest->response->body);
|
500 |
+
return (string) $body->UploadId;
|
501 |
+
}
|
502 |
+
|
503 |
+
// It is a programming error if we reach this line
|
504 |
+
return false;
|
505 |
+
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
/* Upload a part of a multi-part set (http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html)
|
510 |
+
* The chunk is read into memory, so make sure that you have enough (or patch this function to work another way!)
|
511 |
+
*
|
512 |
+
* @param string $bucket Bucket name
|
513 |
+
* @param string $uri Object URI
|
514 |
+
* @param string $uploadId uploadId returned previously from initiateMultipartUpload
|
515 |
+
* @param integer $partNumber sequential part number to upload
|
516 |
+
* @param string $filePath file to upload content from
|
517 |
+
* @param integer $partSize number of bytes in each part (though final part may have fewer) - pass the same value each time (for this particular upload) - default 5Mb (which is Amazon's minimum)
|
518 |
+
* @return string (ETag) | false
|
519 |
+
*/
|
520 |
+
|
521 |
+
public static function uploadPart ($bucket, $uri, $uploadId, $filePath, $partNumber, $partSize = 5242880)
|
522 |
+
{
|
523 |
+
|
524 |
+
$rest = new S3Request('PUT', $bucket, $uri, self::$endpoint);
|
525 |
+
$rest->setParameter('partNumber', $partNumber);
|
526 |
+
$rest->setParameter('uploadId', $uploadId);
|
527 |
+
|
528 |
+
// Where to begin
|
529 |
+
$fileOffset = ($partNumber - 1 ) * $partSize;
|
530 |
+
|
531 |
+
// Download the smallest of the remaining bytes and the part size
|
532 |
+
$fileBytes = min(filesize($filePath) - $fileOffset, $partSize);
|
533 |
+
if ($fileBytes < 0) $fileBytes = 0;
|
534 |
+
|
535 |
+
$rest->setHeader('Content-Type', 'application/octet-stream');
|
536 |
+
$rest->data = "";
|
537 |
+
|
538 |
+
$handle = fopen($filePath, "rb");
|
539 |
+
if ($fileOffset >0) fseek($handle, $fileOffset);
|
540 |
+
$bytes_read = 0;
|
541 |
+
|
542 |
+
while ($fileBytes >0) {
|
543 |
+
$read = fread($handle, min($fileBytes, 32768));
|
544 |
+
$fileBytes = $fileBytes - strlen($read);
|
545 |
+
$bytes_read += strlen($read);
|
546 |
+
$rest->data = $rest->data . $read;
|
547 |
+
}
|
548 |
+
|
549 |
+
fclose($handle);
|
550 |
+
|
551 |
+
$rest->setHeader('Content-MD5', base64_encode(md5($rest->data, true)));
|
552 |
+
$rest->size = $bytes_read;
|
553 |
+
|
554 |
+
$rest = $rest->getResponse();
|
555 |
+
if ($rest->error === false && $rest->code !== 200)
|
556 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
557 |
+
if ($rest->error !== false)
|
558 |
+
{
|
559 |
+
self::__triggerError(sprintf("S3::uploadPart(): [%s] %s",
|
560 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
561 |
+
return false;
|
562 |
+
}
|
563 |
+
return $rest->headers['hash'];
|
564 |
+
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* Complete a multi-part upload (http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html)
|
569 |
+
*
|
570 |
+
* @param string $bucket Bucket name
|
571 |
+
* @param string $uri Object URI
|
572 |
+
* @param string $uploadId uploadId returned previously from initiateMultipartUpload
|
573 |
+
* @param array $parts an ordered list of eTags of previously uploaded parts from uploadPart
|
574 |
+
* @return boolean
|
575 |
+
*/
|
576 |
+
|
577 |
+
public static function completeMultipartUpload ($bucket, $uri, $uploadId, $parts)
|
578 |
+
{
|
579 |
+
$rest = new S3Request('POST', $bucket, $uri, self::$endpoint);
|
580 |
+
$rest->setParameter('uploadId', $uploadId);
|
581 |
+
|
582 |
+
$xml = "<CompleteMultipartUpload>\n";
|
583 |
+
$partno = 1;
|
584 |
+
foreach ($parts as $etag) {
|
585 |
+
$xml .= "<Part><PartNumber>$partno</PartNumber><ETag>$etag</ETag></Part>\n";
|
586 |
+
$partno++;
|
587 |
+
}
|
588 |
+
$xml .= "</CompleteMultipartUpload>";
|
589 |
+
|
590 |
+
$rest->data = $xml;
|
591 |
+
$rest->size = strlen($rest->data);
|
592 |
+
$rest->setHeader('Content-Type', 'application/xml');
|
593 |
+
|
594 |
+
$rest = $rest->getResponse();
|
595 |
+
if ($rest->error === false && $rest->code !== 200)
|
596 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
597 |
+
if ($rest->error !== false)
|
598 |
+
{
|
599 |
+
self::__triggerError(sprintf("S3::completeMultipartUpload(): [%s] %s",
|
600 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
601 |
+
return false;
|
602 |
+
}
|
603 |
+
return true;
|
604 |
+
|
605 |
+
}
|
606 |
+
|
607 |
+
/**
|
608 |
+
* Abort a multi-part upload (http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadAbort.html)
|
609 |
+
*
|
610 |
+
* @param string $bucket Bucket name
|
611 |
+
* @param string $uri Object URI
|
612 |
+
* @param string $uploadId uploadId returned previously from initiateMultipartUpload
|
613 |
+
* @return boolean
|
614 |
+
*/
|
615 |
+
|
616 |
+
public static function abortMultipartUpload ($bucket, $uri, $uploadId)
|
617 |
+
{
|
618 |
+
$rest = new S3Request('DELETE', $bucket, $uri, self::$endpoint);
|
619 |
+
$rest->setParameter('uploadId', $uploadId);
|
620 |
+
$rest = $rest->getResponse();
|
621 |
+
if ($rest->error === false && $rest->code !== 204)
|
622 |
+
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
|
623 |
+
if ($rest->error !== false)
|
624 |
+
{
|
625 |
+
self::__triggerError(sprintf("S3::abortMultipartUpload(): [%s] %s",
|
626 |
+
$rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
|
627 |
+
return false;
|
628 |
+
}
|
629 |
+
return true;
|
630 |
+
}
|
631 |
|
632 |
/**
|
633 |
* Put an object
|
1969 |
if (array_key_exists('acl', $this->parameters) ||
|
1970 |
array_key_exists('location', $this->parameters) ||
|
1971 |
array_key_exists('torrent', $this->parameters) ||
|
1972 |
+
array_key_exists('logging', $this->parameters) ||
|
1973 |
+
array_key_exists('partNumber', $this->parameters) ||
|
1974 |
+
array_key_exists('uploads', $this->parameters) ||
|
1975 |
+
array_key_exists('uploadId', $this->parameters))
|
1976 |
$this->resource .= $query;
|
1977 |
}
|
1978 |
$url = (S3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
|
2051 |
switch ($this->verb)
|
2052 |
{
|
2053 |
case 'GET': break;
|
2054 |
+
case 'PUT': case 'POST':
|
2055 |
if ($this->fp !== false)
|
2056 |
{
|
2057 |
curl_setopt($curl, CURLOPT_PUT, true);
|
readme.txt
CHANGED
@@ -8,7 +8,7 @@ Donate link: http://david.dw-perspective.org.uk/donate
|
|
8 |
License: GPLv3 or later
|
9 |
|
10 |
== Upgrade Notice ==
|
11 |
-
Updated to latest S3 library
|
12 |
|
13 |
== Description ==
|
14 |
|
@@ -70,8 +70,8 @@ Contact me! This is a complex plugin and the only way I can ensure it's robust i
|
|
70 |
|
71 |
== Changelog ==
|
72 |
|
73 |
-
= 0.9.
|
74 |
-
* Updated to latest S3.php library
|
75 |
|
76 |
= 0.9.10 - 11/22/2012 =
|
77 |
* Completed basic Google Drive support (thanks to Sorin Iclanzan, code taken from "Backup" plugin under GPLv3+); now supporting uploading, purging and restoring - i.e. full UpdraftPlus functionality
|
8 |
License: GPLv3 or later
|
9 |
|
10 |
== Upgrade Notice ==
|
11 |
+
Updated to latest S3 library with patch for chunked uploading (for future use)
|
12 |
|
13 |
== Description ==
|
14 |
|
70 |
|
71 |
== Changelog ==
|
72 |
|
73 |
+
= 0.9.12 - 12/06/2012 =
|
74 |
+
* Updated to latest S3.php library with chunked uploading patch (for future improvements)
|
75 |
|
76 |
= 0.9.10 - 11/22/2012 =
|
77 |
* Completed basic Google Drive support (thanks to Sorin Iclanzan, code taken from "Backup" plugin under GPLv3+); now supporting uploading, purging and restoring - i.e. full UpdraftPlus functionality
|
updraftplus.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: UpdraftPlus - Backup/Restore
|
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
-
Version: 0.9.
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPL3
|
10 |
Author URI: http://wordshell.net
|
@@ -62,7 +62,7 @@ define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php');
|
|
62 |
|
63 |
class UpdraftPlus {
|
64 |
|
65 |
-
var $version = '0.9.
|
66 |
|
67 |
var $dbhandle;
|
68 |
var $errors = array();
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
+
Version: 0.9.12
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPL3
|
10 |
Author URI: http://wordshell.net
|
62 |
|
63 |
class UpdraftPlus {
|
64 |
|
65 |
+
var $version = '0.9.12';
|
66 |
|
67 |
var $dbhandle;
|
68 |
var $errors = array();
|