/// <summary> /// Tests the CloudBackupService classes. The content of a storage account /// is listed. A file is uploaded, downloaded, and finally deleted. /// </summary> public void test_CloudBackupService() { Console.WriteLine("About to start a test using CloudBackupService." + " Press any key to continue, or ESC to skip.\n"); if (hit_esc_key()) { return; } var backup_services = create_cloud_backup_services_from_xml(cloud_backup_services_xml); // Choose one of the "backup_services" for use in testing. CloudBackupService backup_service = backup_services[1]; string bucket_name = "xxxxxxxx"; // Choose bucket name Console.WriteLine("Testing using " + backup_service.Name + "\\" + bucket_name); Console.WriteLine("Listing objects:"); foreach (var obj in backup_service.list_objects(bucket_name, null)) { Console.WriteLine(new String(' ', 4) + obj); } Console.WriteLine("Manually confirm that this is correct."); pause(); // generate files for testing string longer_file_path = @"E:\temp\temp2\temp.bin"; string shorter_file_path = @"E:\temp\temp2\temp_shorter.bin"; string download_file_path = @"E:\temp\temp2\temp_downloaded.bin"; string key_name = Path.GetFileName(longer_file_path); // generate shorter file var random = new Random(); byte[] buffer = new byte[1 * 1024]; random.NextBytes(buffer); using (FileStream fs_short = new FileStream(shorter_file_path, FileMode.Create, FileAccess.Write)) { fs_short.Write(buffer, 0, buffer.Length); } // generate longer file using (FileStream fs_long = new FileStream(longer_file_path, FileMode.Create, FileAccess.Write)) { fs_long.Write(buffer, 0, buffer.Length); for (int i = 0; i < 10; i++) { random.NextBytes(buffer); fs_long.Write(buffer, 0, buffer.Length); } } // upload file Console.WriteLine("Uploading file."); using (FileStream fs_long = new FileStream(longer_file_path, FileMode.Open, FileAccess.Read)) { backup_service.upload(fs_long, bucket_name, key_name); } // download partial and compare file Console.WriteLine("Downloading the start of the file and checking."); using (FileStream fs_downloaded = new FileStream(download_file_path, FileMode.Create, FileAccess.Write)) { backup_service.download(bucket_name, key_name, fs_downloaded, 0, 1 * 1024); } Debug.Assert(compare_files(shorter_file_path, download_file_path)); // download full file and compare file Console.WriteLine("Downloading the full file and checking."); using (FileStream fs_downloaded = new FileStream(download_file_path, FileMode.Create, FileAccess.Write)) { backup_service.download(bucket_name, key_name, fs_downloaded); } Debug.Assert(compare_files(longer_file_path, download_file_path)); // Test to see if downloading too many bytes cause errors? using (FileStream fs_downloaded = new FileStream(download_file_path, FileMode.Create, FileAccess.Write)) { backup_service.download(bucket_name, key_name, fs_downloaded, 0, 1024 * 1024); } Debug.Assert(compare_files(longer_file_path, download_file_path)); // delete file Console.WriteLine("Deleting the file and checking."); backup_service.delete(bucket_name, key_name); bool found = false; foreach (var obj in backup_service.list_objects(bucket_name, null)) { if (obj.Equals(key_name)) { found = true; break; } } Debug.Assert(found == false); Console.WriteLine("CloudBackupService test completed."); }
/// <summary> /// Tests EncryptStream and DecryptStream using cloud storage. A single /// file is uploaded in encrypted form and then downloaded. /// </summary> public void test_Encrypt_and_Decrypt_streams_on_cloud() { Console.WriteLine("About to upload a file to the cloud and download it back, " + "using EncryptStream and DecryptStream. Press any key to continue, or ESC to skip.\n"); if (hit_esc_key()) { return; } var backup_services = create_cloud_backup_services_from_xml(cloud_backup_services_xml); // Choose one of the "backup_services" for use in testing. CloudBackupService backup_service = backup_services[2]; string bucket_name = "xxxxxxxx"; string original_file = @"E:\temp\temp\temp.bin"; string base_path = @"E:\temp\temp"; string relative_path = original_file.Substring(base_path.Length + 1); string decrypted_file = @"E:\temp\temp2\temp.bin"; var encrypt_stream = new EncryptStream(); var decrypt_stream = new DecryptStream(); Random random = new Random(); byte[] buffer = new byte[1024]; // create random file using (var fs = new FileStream(original_file, FileMode.Create, FileAccess.Write)) { for (int j = 0; j < 640; j++) { random.NextBytes(buffer); fs.Write(buffer, 0, buffer.Length); } } // encrypted upload Console.WriteLine("Encrypting and uploading file to the cloud."); encrypt_stream.reset(original_file, relative_path, key); backup_service.upload(encrypt_stream, bucket_name, "temp.bin"); Console.WriteLine("The file has been encrypted and uploaded to the cloud."); Thread.Sleep(2000); // download and decrypt decrypt_stream.reset(key, full_path_request_handler); // be sure the download can be done in pieces backup_service.download(bucket_name, "temp.bin", decrypt_stream, 0, 1024); Console.WriteLine("The first 1kB header says the pre-encrypt file size is " + file_pre_encrypt_size + " bytes."); backup_service.download(bucket_name, "temp.bin", decrypt_stream, 1024, file_pre_encrypt_size); decrypt_stream.Flush(); backup_service.delete(bucket_name, "temp.bin"); Debug.Assert(compare_files(original_file, decrypted_file)); Console.WriteLine("EncryptStream and DecryptStream has been tested using cloud storage.\n"); }
/// <summary> /// Goes over every file in this directory / bucket and download its first 1kB /// to get information. Accumulate data in the restore_info object. /// </summary> /// <param name="restore_info">The "file_names" field can be null, which causes /// file names to not get recorded. This will save memory.</param> public void get_info(RestoreInfo restore_info) { // Get a list of alt_file_names. These look like "a1000.bin" string[] alt_file_names = get_alt_file_names(); // To get information, it's only necessary to read the early part of the file. const int bytes_to_read = 1024; byte[] buffer = new byte[bytes_to_read]; int files_processed = 0; // report progress to the GUI // For each alt_file_name, extract info foreach (var alt_file_name in alt_file_names) { // Check alt_file_name format. Work only on files that has the right format. string prefix = null; UInt32 id; break_down_alt_file_name(alt_file_name, ref prefix, out id); if (prefix != null) { // Set up before getting the first bytes. decrypt_stream.reset(null, get_info_handler); handler_called = false; // Read the early bytes. if (cloud_backup == null) { using (var fs = new FileStream(alt_file_name, FileMode.Open, FileAccess.Read)) { int bytes_read = fs.Read(buffer, 0, bytes_to_read); decrypt_stream.Write(buffer, 0, bytes_read); } } else { cloud_backup.download(backup_destination_base, alt_file_name, decrypt_stream, 0, bytes_to_read); } // At this point "handler_called" should have happened. if (handler_called == false) { throw new Exception("Restore file error. While examining the file at \"" + backup_destination_name + "\\" + backup_destination_base + "\\" + alt_file_name + "\", failed to determine the true file name after reading the first " + bytes_to_read + " bytes."); } // At this point, the get_info_handler(...) handler has updated // relative_path and file_pre_encrypt_size. restore_info.total_file_size += total_file_length; // Extract embedded_prefix from relative_path. int index = relative_path.IndexOf('\\'); // If index == -1, this file has no prefix. This should be an error. // But throwing exception aborts the restore. So continue for now. // Just ignore this file. if (index > 0) { string embedded_prefix = relative_path.Substring(0, index); restore_info.embedded_prefixes.Add(embedded_prefix); // The file_names is optional, so test for null. if (restore_info.file_names != null) { if (restore_info.file_names.ContainsKey(embedded_prefix) == false) { restore_info.file_names.Add(embedded_prefix, new List <string>()); } restore_info.file_names[embedded_prefix].Add(relative_path.Substring(index + 1)); } // report progress to the user files_processed++; if (report_event != null) { if (files_processed == 10) { report_event(AppEventType.FILES_PROCESSED, files_processed); files_processed = 0; } } } } } // end of: foreach (var alt_file_name in alt_file_names) if (report_event != null) { report_event(AppEventType.FILES_PROCESSED, files_processed); files_processed = 0; } }