Example #1
0
 function backup($backup_array)
 {
     global $updraftplus;
     $updraft_dir = $updraftplus->backups_dir_location() . '/';
     $path = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_path'));
     $authurl = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_authurl', 'https://auth.api.rackspacecloud.com');
     // 		if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
     // 			$container = $bmatches[1];
     // 			$path = $bmatches[2];
     // 		} else {
     // 			$container = $path;
     // 			$path = "";
     // 		}
     $container = $path;
     $user = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_user');
     $apikey = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_apikey');
     try {
         $conn = $this->getCF($user, $apikey, $authurl, UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts'));
         $cont_obj = $conn->create_container($container);
     } catch (AuthenticationException $e) {
         $updraftplus->log('Cloud Files authentication failed (' . $e->getMessage() . ')');
         $updraftplus->log(sprintf(__('%s authentication failed', 'updraftplus'), 'Cloud Files') . ' (' . $e->getMessage() . ')', 'error');
         return false;
     } catch (NoSuchAccountException $s) {
         $updraftplus->log('Cloud Files authentication failed (' . $e->getMessage() . ')');
         $updraftplus->log(sprintf(__('%s authentication failed', 'updraftplus'), 'Cloud Files') . ' (' . $e->getMessage() . ')', 'error');
         return false;
     } catch (Exception $e) {
         $updraftplus->log('Cloud Files error - failed to create and access the container (' . $e->getMessage() . ')');
         $updraftplus->log(__('Cloud Files error - failed to create and access the container', 'updraftplus') . ' (' . $e->getMessage() . ')', 'error');
         return;
     }
     $chunk_size = 5 * 1024 * 1024;
     foreach ($backup_array as $key => $file) {
         $fullpath = $updraft_dir . $file;
         $orig_file_size = filesize($fullpath);
         // 			$cfpath = ($path == '') ? $file : "$path/$file";
         // 			$chunk_path = ($path == '') ? "chunk-do-not-delete-$file" : "$path/chunk-do-not-delete-$file";
         $cfpath = $file;
         $chunk_path = "chunk-do-not-delete-{$file}";
         try {
             $object = new UpdraftPlus_CF_Object($cont_obj, $cfpath);
             $object->content_type = "application/zip";
             $uploaded_size = isset($object->content_length) ? $object->content_length : 0;
             if ($uploaded_size <= $orig_file_size) {
                 $fp = @fopen($fullpath, "rb");
                 if (!$fp) {
                     $updraftplus->log("Cloud Files: failed to open file: {$fullpath}");
                     $updraftplus->log("{$file}: " . sprintf(__('%s Error: Failed to open local file', 'updraftplus'), 'Cloud Files'), 'error');
                     return false;
                 }
                 $chunks = floor($orig_file_size / $chunk_size);
                 // There will be a remnant unless the file size was exactly on a 5Mb boundary
                 if ($orig_file_size % $chunk_size > 0) {
                     $chunks++;
                 }
                 $updraftplus->log("Cloud Files upload: {$file} (chunks: {$chunks}) -> cloudfiles://{$container}/{$cfpath} ({$uploaded_size})");
                 if ($chunks < 2) {
                     try {
                         $object->load_from_filename($fullpath);
                         $updraftplus->log("Cloud Files regular upload: success");
                         $updraftplus->uploaded_file($file);
                     } catch (Exception $e) {
                         $updraftplus->log("Cloud Files regular upload: failed ({$file}) (" . $e->getMessage() . ")");
                         $updraftplus->log("{$file}: " . sprintf(__('%s Error: Failed to upload', 'updraftplus'), 'Cloud Files'), 'error');
                     }
                 } else {
                     $errors_so_far = 0;
                     for ($i = 1; $i <= $chunks; $i++) {
                         $upload_start = ($i - 1) * $chunk_size;
                         // The file size -1 equals the byte offset of the final byte
                         $upload_end = min($i * $chunk_size - 1, $orig_file_size - 1);
                         $upload_remotepath = $chunk_path . "_{$i}";
                         // Don't forget the +1; otherwise the last byte is omitted
                         $upload_size = $upload_end - $upload_start + 1;
                         $chunk_object = new UpdraftPlus_CF_Object($cont_obj, $upload_remotepath);
                         $chunk_object->content_type = "application/zip";
                         // Without this, some versions of Curl add Expect: 100-continue, which results in Curl then giving this back: curl error: 55) select/poll returned error
                         // Didn't make the difference - instead we just check below for actual success even when Curl reports an error
                         // $chunk_object->headers = array('Expect' => '');
                         $remote_size = isset($chunk_object->content_length) ? $chunk_object->content_length : 0;
                         if ($remote_size >= $upload_size) {
                             $updraftplus->log("Cloud Files: Chunk {$i} ({$upload_start} - {$upload_end}): already uploaded");
                         } else {
                             $updraftplus->log("Cloud Files: Chunk {$i} ({$upload_start} - {$upload_end}): begin upload");
                             // Upload the chunk
                             fseek($fp, $upload_start);
                             try {
                                 $chunk_object->write($fp, $upload_size, false);
                                 $updraftplus->record_uploaded_chunk(round(100 * $i / $chunks, 1), $i, $fullpath);
                             } catch (Exception $e) {
                                 $updraftplus->log("Cloud Files chunk upload: error: ({$file} / {$i}) (" . $e->getMessage() . ")");
                                 // Experience shows that Curl sometimes returns a select/poll error (curl error 55) even when everything succeeded. Google seems to indicate that this is a known bug.
                                 $chunk_object = new UpdraftPlus_CF_Object($cont_obj, $upload_remotepath);
                                 $chunk_object->content_type = "application/zip";
                                 $remote_size = isset($chunk_object->content_length) ? $chunk_object->content_length : 0;
                                 if ($remote_size >= $upload_size) {
                                     $updraftplus->log("{$file}: Chunk now exists; ignoring error (presuming it was an apparently known curl bug)");
                                 } else {
                                     $updraftplus->log("{$file}: " . sprintf(__('%s Error: Failed to upload', 'updraftplus'), 'Cloud Files'), 'error');
                                     $errors_so_far++;
                                     if ($errors_so_far >= 3) {
                                         return false;
                                     }
                                 }
                             }
                         }
                     }
                     if ($errors_so_far) {
                         return false;
                     }
                     // All chunks are uploaded - now upload the manifest
                     try {
                         $object->manifest = $container . "/" . $chunk_path . "_";
                         // Put a zero-length file
                         $object->write("", 0, false);
                         $object->sync_manifest();
                         $updraftplus->log("Cloud Files upload: success");
                         $updraftplus->uploaded_file($file);
                         // 						} catch (InvalidResponseException $e) {
                     } catch (Exception $e) {
                         $updraftplus->log('Cloud Files error - failed to re-assemble chunks (' . $e->getMessage() . ')');
                         $updraftplus->log(sprintf(__('%s error - failed to re-assemble chunks', 'updraftplus'), 'Cloud Files') . ' (' . $e->getMessage() . ')', 'error');
                         return false;
                     }
                 }
             }
         } catch (Exception $e) {
             $updraftplus->log(__('Cloud Files error - failed to upload file', 'updraftplus') . ' (' . $e->getMessage() . ')');
             $updraftplus->log(sprintf(__('%s error - failed to upload file', 'updraftplus'), 'Cloud Files') . ' (' . $e->getMessage() . ')', 'error');
             return false;
         }
     }
     $updraftplus->prune_retained_backups('cloudfiles', $this, array('cloudfiles_object' => $cont_obj, 'cloudfiles_orig_path' => $path, 'cloudfiles_container' => $container));
 }