mirror of
https://github.com/gilbertchen/duplicacy
synced 2025-12-15 07:43:21 +00:00
Fixed handling of repository ids with spaces in the b2 backend
Usually a repository id should not contain spaces or other non-alphanum characters, but if it does we should be able to handle it correctly. This commit fixes the b2 backend to convert file names in a proper way.
This commit is contained in:
@@ -413,16 +413,16 @@ func (client *B2Client) ListFileNames(threadIndex int, startFileName string, sin
|
|||||||
input["prefix"] = client.StorageDir
|
input["prefix"] = client.StorageDir
|
||||||
|
|
||||||
for {
|
for {
|
||||||
url := client.getAPIURL() + "/b2api/v1/b2_list_file_names"
|
apiURL := client.getAPIURL() + "/b2api/v1/b2_list_file_names"
|
||||||
requestHeaders := map[string]string{}
|
requestHeaders := map[string]string{}
|
||||||
requestMethod := http.MethodPost
|
requestMethod := http.MethodPost
|
||||||
var requestInput interface{}
|
var requestInput interface{}
|
||||||
requestInput = input
|
requestInput = input
|
||||||
if includeVersions {
|
if includeVersions {
|
||||||
url = client.getAPIURL() + "/b2api/v1/b2_list_file_versions"
|
apiURL = client.getAPIURL() + "/b2api/v1/b2_list_file_versions"
|
||||||
} else if singleFile {
|
} else if singleFile {
|
||||||
// handle a single file with no versions as a special case to download the last byte of the file
|
// handle a single file with no versions as a special case to download the last byte of the file
|
||||||
url = client.getDownloadURL() + "/file/" + client.BucketName + "/" + B2Escape(client.StorageDir + startFileName)
|
apiURL = client.getDownloadURL() + "/file/" + client.BucketName + "/" + B2Escape(client.StorageDir + startFileName)
|
||||||
// requesting byte -1 works for empty files where 0-0 fails with a 416 error
|
// requesting byte -1 works for empty files where 0-0 fails with a 416 error
|
||||||
requestHeaders["Range"] = "bytes=-1"
|
requestHeaders["Range"] = "bytes=-1"
|
||||||
// HEAD request
|
// HEAD request
|
||||||
@@ -432,7 +432,7 @@ func (client *B2Client) ListFileNames(threadIndex int, startFileName string, sin
|
|||||||
var readCloser io.ReadCloser
|
var readCloser io.ReadCloser
|
||||||
var responseHeader http.Header
|
var responseHeader http.Header
|
||||||
var err error
|
var err error
|
||||||
readCloser, responseHeader, _, err = client.call(threadIndex, url, requestMethod, requestHeaders, requestInput)
|
readCloser, responseHeader, _, err = client.call(threadIndex, apiURL, requestMethod, requestHeaders, requestInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -445,7 +445,7 @@ func (client *B2Client) ListFileNames(threadIndex int, startFileName string, sin
|
|||||||
|
|
||||||
if singleFile && !includeVersions {
|
if singleFile && !includeVersions {
|
||||||
if responseHeader == nil {
|
if responseHeader == nil {
|
||||||
LOG_DEBUG("BACKBLAZE_LIST", "%s did not return headers", url)
|
LOG_DEBUG("BACKBLAZE_LIST", "%s did not return headers", apiURL)
|
||||||
return []*B2Entry{}, nil
|
return []*B2Entry{}, nil
|
||||||
}
|
}
|
||||||
requiredHeaders := []string{
|
requiredHeaders := []string{
|
||||||
@@ -459,11 +459,17 @@ func (client *B2Client) ListFileNames(threadIndex int, startFileName string, sin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(missingKeys) > 0 {
|
if len(missingKeys) > 0 {
|
||||||
return nil, fmt.Errorf("%s missing headers: %s", url, missingKeys)
|
return nil, fmt.Errorf("%s missing headers: %s", apiURL, missingKeys)
|
||||||
}
|
}
|
||||||
// construct the B2Entry from the response headers of the download request
|
// construct the B2Entry from the response headers of the download request
|
||||||
fileID := responseHeader.Get("x-bz-file-id")
|
fileID := responseHeader.Get("x-bz-file-id")
|
||||||
fileName := responseHeader.Get("x-bz-file-name")
|
fileName := responseHeader.Get("x-bz-file-name")
|
||||||
|
unescapedFileName, err := url.QueryUnescape(fileName)
|
||||||
|
if err == nil {
|
||||||
|
fileName = unescapedFileName
|
||||||
|
} else {
|
||||||
|
LOG_WARN("BACKBLAZE_UNESCAPE", "Failed to unescape the file name %s", fileName)
|
||||||
|
}
|
||||||
fileAction := "upload"
|
fileAction := "upload"
|
||||||
// byte range that is returned: "bytes #-#/#
|
// byte range that is returned: "bytes #-#/#
|
||||||
rangeString := responseHeader.Get("Content-Range")
|
rangeString := responseHeader.Get("Content-Range")
|
||||||
@@ -476,10 +482,10 @@ func (client *B2Client) ListFileNames(threadIndex int, startFileName string, sin
|
|||||||
// this should only execute if the requested file is empty and the range request didn't result in a Content-Range header
|
// this should only execute if the requested file is empty and the range request didn't result in a Content-Range header
|
||||||
fileSize, _ = strconv.ParseInt(lengthString, 0, 64)
|
fileSize, _ = strconv.ParseInt(lengthString, 0, 64)
|
||||||
if fileSize != 0 {
|
if fileSize != 0 {
|
||||||
return nil, fmt.Errorf("%s returned non-zero file length", url)
|
return nil, fmt.Errorf("%s returned non-zero file length", apiURL)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("could not parse headers returned by %s", url)
|
return nil, fmt.Errorf("could not parse headers returned by %s", apiURL)
|
||||||
}
|
}
|
||||||
fileUploadTimestamp, _ := strconv.ParseInt(responseHeader.Get("X-Bz-Upload-Timestamp"), 0, 64)
|
fileUploadTimestamp, _ := strconv.ParseInt(responseHeader.Get("X-Bz-Upload-Timestamp"), 0, 64)
|
||||||
|
|
||||||
|
|||||||
@@ -204,7 +204,6 @@ func (storage *B2Storage) GetFileInfo(threadIndex int, filePath string) (exist b
|
|||||||
// DownloadFile reads the file at 'filePath' into the chunk.
|
// DownloadFile reads the file at 'filePath' into the chunk.
|
||||||
func (storage *B2Storage) DownloadFile(threadIndex int, filePath string, chunk *Chunk) (err error) {
|
func (storage *B2Storage) DownloadFile(threadIndex int, filePath string, chunk *Chunk) (err error) {
|
||||||
|
|
||||||
filePath = strings.Replace(filePath, " ", "%20", -1)
|
|
||||||
readCloser, _, err := storage.client.DownloadFile(threadIndex, filePath)
|
readCloser, _, err := storage.client.DownloadFile(threadIndex, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -218,7 +217,6 @@ func (storage *B2Storage) DownloadFile(threadIndex int, filePath string, chunk *
|
|||||||
|
|
||||||
// UploadFile writes 'content' to the file at 'filePath'.
|
// UploadFile writes 'content' to the file at 'filePath'.
|
||||||
func (storage *B2Storage) UploadFile(threadIndex int, filePath string, content []byte) (err error) {
|
func (storage *B2Storage) UploadFile(threadIndex int, filePath string, content []byte) (err error) {
|
||||||
filePath = strings.Replace(filePath, " ", "%20", -1)
|
|
||||||
return storage.client.UploadFile(threadIndex, filePath, content, storage.UploadRateLimit/storage.client.Threads)
|
return storage.client.UploadFile(threadIndex, filePath, content, storage.UploadRateLimit/storage.client.Threads)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user