Beispiel #1
0
        public (string, BackupRecord) GetBackupHashAndRecord(string bsname, string prefix, int offset = 0)
        {
            var bset  = LoadBackupSet(bsname);
            var match = HashByPrefix(bsname, prefix);

            if (match == null || match.Value.multiplematches == true)
            {
                // TODO: throw this exception out of HashByPrefix?
                throw new KeyNotFoundException();
            }
            int pidx = 0;

            for (int i = 0; i < bset.Backups.Count; i++)
            {
                if (bset.Backups[i].hash.SequenceEqual(match.Value.singlematchhash))
                {
                    pidx = i;
                    break;
                }
            }
            int bidx = pidx + offset;

            if (bidx >= 0 && bidx < bset.Backups.Count)
            {
                return(HashTools.ByteArrayToHexViaLookup32(bset.Backups[bidx].hash).ToLower(), GetBackupRecord(bsname, bset.Backups[bidx].hash));
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
Beispiel #2
0
        public IEnumerable <string> GetBackupsAndMetadataReferencesAsStrings(BackupSetReference bsname)
        {
            var bset = LoadBackupSet(bsname);

            foreach ((byte[] backupref, bool _) in bset.Backups)
            {
                yield return(HashTools.ByteArrayToHexViaLookup32(backupref));

                foreach (byte[] reference in Dependencies.Blobs.GetAllBlobReferences(backupref,
                                                                                     BlobLocation.BlobType.BackupRecord, false, false))
                {
                    yield return(HashTools.ByteArrayToHexViaLookup32(reference));
                }
            }
        }
Beispiel #3
0
 public Task DeleteBlobAsync(byte[] hash, string fileId)
 {
     return(DeleteFileAsync(Path.Combine(BlobSaveDirectory, HashTools.ByteArrayToHexViaLookup32(hash)), fileId));
 }
Beispiel #4
0
 public Task <(byte[] encryptedHash, string fileId)> StoreBlobAsync(byte[] hash, byte[] data)
 {
     return(StoreFileAsync(Path.Combine(BlobSaveDirectory, HashTools.ByteArrayToHexViaLookup32(hash)), hash, data));
 }
Beispiel #5
0
 public Task <byte[]> LoadBlobAsync(byte[] hash)
 {
     return(LoadFileAsync(Path.Combine(BlobSaveDirectory, HashTools.ByteArrayToHexViaLookup32(hash))));
 }
Beispiel #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="file"></param>
        /// <param name="hash"></param>
        /// <param name="data"></param>
        /// <returns>fileId</returns>
        private async Task <(byte[] encryptedHash, string fileId)> StoreFileAsync(string file, byte[] hash, byte[] data, bool preventEncryption = false)
        {
            async Task <GetUploadUrlResponse> GetUploadUrl(int attempts = 0)
            {
                if (AuthResp == null)
                {
                    AuthResp = await AuthorizeAccount();
                }
                Delay();
                try
                {
                    var urlresp = await AuthResp.apiUrl
                                  .AppendPathSegment("/b2api/v1/b2_get_upload_url")
                                  .WithHeaders(new { Authorization = AuthResp.authorizationToken })
                                  .PostJsonAsync(new { bucketId = BucketId })
                                  .ReceiveJson <GetUploadUrlResponse>().ConfigureAwait(false);

                    SuccessfulTransmission();
                    return(urlresp);
                }
                catch (FlurlHttpException ex)
                {
                    if (ex.Call.HttpStatus != null && ex.Call.HttpStatus == System.Net.HttpStatusCode.Unauthorized)
                    {
                        AuthResp = null;
                    }
                    else
                    {
                        // Other classes of errors may be congestion related so we increase the delay
                        FailedTransmission();
                    }
                    if (attempts < Retries)
                    {
                        return(await GetUploadUrl(attempts + 1).ConfigureAwait(false));
                    }
                    throw;
                }
            }

            var hashFileId = await UploadData();

            async Task <(byte[] encryptedHash, string fileId)> UploadData(int attempts = 0)
            {
                if (UploadUrlResp == null)
                {
                    UploadUrlResp = await GetUploadUrl();
                }
                Delay();
                try
                {
                    if (Encryptor != null && !preventEncryption)
                    {
                        data = Encryptor.EncryptBytes(data);
                        hash = HashTools.GetSHA1Hasher().ComputeHash(data);
                    }

                    var filecontent = new ByteArrayContent(data);
                    filecontent.Headers.Add("Content-Type", "application/octet-stream");
                    var uploadresp = await UploadUrlResp.uploadUrl
                                     .WithHeaders(new
                    {
                        Authorization     = UploadUrlResp.authorizationToken,
                        X_Bz_File_Name    = file,
                        Content_Length    = data.Length,
                        X_Bz_Content_Sha1 = HashTools.ByteArrayToHexViaLookup32(hash)
                    })
                                     .PostAsync(filecontent)
                                     .ReceiveJson <UploadResponse>().ConfigureAwait(false);

                    SuccessfulTransmission();
                    return(hash, uploadresp.fileId);
                }
                catch (FlurlHttpException ex)
                {
                    if (ex.Call.HttpStatus != null && ex.Call.HttpStatus == System.Net.HttpStatusCode.Unauthorized)
                    {
                        UploadUrlResp = null;
                    }
                    else
                    {
                        // Other classes of errors may be congestion related so we increase the delay
                        FailedTransmission();
                    }

                    if (attempts < Retries)
                    {
                        return(await UploadData(attempts + 1).ConfigureAwait(false));
                    }
                    throw;
                }
            }

            return(hashFileId);
        }
Beispiel #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="prefix"></param>
        /// <returns>Null if no matches, (true, null) for multiple matches, (false, hashstring) for exact match.</returns>
        public (bool multiplematches, byte[] singlematchhash)? HashByPrefix(string bsname, string prefix)
        {
            var bset = LoadBackupSet(bsname);

            // TODO: This implementation is pretty slow, could be improved with a better data structure like a trie or DAFSA
            // also if this becomes an issue, keep a s
            prefix = prefix.ToLower();
            List <string> hashes  = new List <string>(from backup in bset.Backups select HashTools.ByteArrayToHexViaLookup32(backup.hash));
            List <string> matches = new List <string>(from h in hashes where h.ToLower().StartsWith(prefix.ToLower()) select h);

            if (matches.Count == 0)
            {
                return(null);
            }
            else if (matches.Count > 1)
            {
                return(true, null);
            }
            else
            {
                return(false, HashTools.HexStringToByteArray(matches[0]));
            }
        }
Beispiel #8
0
        public (string, BackupRecord) GetBackupHashAndRecord(string bsname, int offset = 0)
        {
            var bset = LoadBackupSet(bsname);

            return(GetBackupHashAndRecord(bsname, HashTools.ByteArrayToHexViaLookup32(bset.Backups[bset.Backups.Count - 1].hash).ToLower(), offset));
        }