UpdraftPlus WordPress Backup Plugin - Version 0.9.12

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 Icon 128x128 UpdraftPlus WordPress Backup Plugin
Version 0.9.12
Comparing to
See all releases

Code changes from version 0.9.11 to 0.9.12

Files changed (3) hide show
  1. includes/S3.php +180 -3
  2. readme.txt +3 -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('website', $this->parameters) ||
1798
- array_key_exists('logging', $this->parameters))
 
 
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': // POST only used for CloudFront
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 (to prepare for future enhancements)
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.11 - 12/06/2012 =
74
- * Updated to latest S3.php library (to allow for future enhancements)
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.11
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.11';
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();