public string Sign(ParamUrl requestUrl, OAuthToken authToken) { string timestamp = timeStamp(); string nonce = random.Next(0, int.MaxValue).ToString(); string token = (authToken == null)? String.Empty : authToken.Token; string secret = (authToken == null)? String.Empty : authToken.Secret; string signature = string.Format("{0}&{1}", consumerSecret, secret); requestUrl.Add("oauth_consumer_key", consumerKey); requestUrl.Add("oauth_nonce", nonce); requestUrl.Add("oauth_timestamp", timestamp); requestUrl.Add("oauth_signature_method", "PLAINTEXT"); requestUrl.Add("oauth_version", "1.0"); requestUrl.Add("oauth_signature", Uri.EscapeDataString(signature)); if (!String.IsNullOrEmpty(token)) requestUrl.Add("oauth_token", token); return requestUrl.ToString(); }
public async Task DeleteAsync(DFileInfo file) { var dFile = (DropboxFileInfo)file; var url = new ParamUrl(DropboxConfig.DeleteUrl); url.Add("root", DropboxConfig.AccessType); url.Add("path", percentEncoding(dFile.Path)); await queryServer(url).ConfigureAwait(false); file.Parent.Contents.Remove(file.Name.ToLowerInvariant()); file = null; }
public async Task<Stream> GetDownloadStreamAsync(DFileInfo file) { if (file.IsDirectory) throw new NotSupportedException("Downloading a folder is not supported."); var dFile = (DropboxFileInfo)file; var url = new StringBuilder(DropboxConfig.DownloadUrl); url.Append(DropboxConfig.AccessType); url.Append(dFile.Path); ParamUrl queryUrl = new ParamUrl(url.ToString()); try { var signedUrl = await signAsync(queryUrl).ConfigureAwait(false); var request = (HttpWebRequest)WebRequest.Create(signedUrl); request.Method = WebRequestMethods.Http.Get; var response = await request.GetResponseAsync().ConfigureAwait(false); return response.GetResponseStream(); } catch (WebException e) { throw parseException(e); } }
public async Task<DFileInfo> UploadFileAsync(DFileInfo destinationFolder, string name, Stream stream, CancellationToken cancellationToken, IProgress<int> progress, long fileSize) { var dDestFolder = (DropboxFileInfo)destinationFolder; string uploadId = null; using (stream) { if (progress != null) progress.Report(0); var buffer = new byte[DropboxConfig.ChunkSize]; long totalUploaded = 0, offset = 0; // Some data is read from the buffer until it is full and we // attempt to push it to the server until it acknowledges all of it. while (true) { int bytesRead = 0, bytesReadThisTime = 0; while (bytesRead < buffer.Length) { bytesReadThisTime = await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead).ConfigureAwait(false); bytesRead += bytesReadThisTime; if (bytesReadThisTime == 0) break; } if (bytesRead == 0) break; int relativeOffset = 0; // relativeOffset shows how many bytes server already accepted. while (relativeOffset < bytesRead) { cancellationToken.ThrowIfCancellationRequested(); var url = new ParamUrl(DropboxConfig.UploadUrl); url.Add("offset", (offset + relativeOffset).ToString()); if (uploadId != null) url.Add("upload_id", uploadId); var signedUrl = await signAsync(url).ConfigureAwait(false); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(signedUrl); request.Method = WebRequestMethods.Http.Put; request.ContentLength = bytesRead - relativeOffset; using (var requestStream = await request.GetRequestStreamAsync().ConfigureAwait(false)) { requestStream.Write(buffer, relativeOffset, bytesRead - relativeOffset); } JToken response; try { var webResponse = await request.GetResponseAsync().ConfigureAwait(false); StreamReader reader = new StreamReader(webResponse.GetResponseStream()); var jsonResult = reader.ReadToEnd(); reader.Close(); response = JToken.Parse(jsonResult); } catch (WebException e) { string message = e.ResponseString(); if (e.HttpStatusCode() == 400 && !string.IsNullOrEmpty(message)) { response = JToken.Parse(message); } else throw parseException(e); } uploadId = (string)response["upload_id"]; relativeOffset = (int)((long)response["offset"] - offset); totalUploaded = offset + relativeOffset; if (progress != null) progress.Report((int)(totalUploaded * 100 / fileSize)); } offset += bytesRead; } } var baseUrl = new StringBuilder(DropboxConfig.UploadFinishUrl); baseUrl.Append(DropboxConfig.AccessType); baseUrl.Append(concatenatePath(dDestFolder.Path, name)); var finalUrl = new ParamUrl(baseUrl.ToString()); finalUrl.Add("upload_id", uploadId); var finishResponse = await queryServer(finalUrl, WebRequestMethods.Http.Post).ConfigureAwait(false); DropboxFileInfo file = new DropboxFileInfo() { Parent = destinationFolder }; setupFileWithMetadata(file, JToken.Parse(finishResponse)); destinationFolder.Contents.Add(name.ToLowerInvariant(), file); return file; }
public async Task SynchronizeAsync() { bool hasMore = true; while (hasMore) { var url = new ParamUrl(DropboxConfig.DeltaUrl); if (!string.IsNullOrEmpty(_cursor)) url.Add("cursor", _cursor); string responseString = await queryServer(url, WebRequestMethods.Http.Post).ConfigureAwait(false); var response = JObject.Parse(responseString); hasMore = (bool)response["has_more"]; // If the reset flag is received, local state should be cleared. if ((bool)response["reset"]) _root.Contents.Clear(); // Set the cursor string for further queries. _cursor = (string)response["cursor"]; foreach (JToken entry in (JArray)response["entries"]) { // The first element is path of the file/folder and the second is metadata. // If the second element is null, file/folder does not exist anymore. var path = (string)entry.First; var metadata = entry.Last; // When splitting the path (/folder/folder/...), the first entry will be empty. var folders = path.Split('/'); // If the second value of the entry is not null, // then it's a metadata for new file or folder. // If it is null, file/folder was deleted. if (metadata.HasValues) addFile(folders, metadata); else removeFile(folders); } } }
public async Task<DFileInfo> CreateFolderAsync(DFileInfo destinationFolder, string name) { string nameKey = name.ToLowerInvariant(); if (destinationFolder.Contents.ContainsKey(nameKey)) throw new FileConflictException("Entry with name specified is already present."); var dParent = (DropboxFileInfo)destinationFolder; string path = concatenatePath(dParent.Path, name); var url = new ParamUrl(DropboxConfig.CreateFolderUrl); url.Add("root", DropboxConfig.AccessType); url.Add("path", path); var response = await queryServer(url).ConfigureAwait(false); var metadata = JObject.Parse(response); var newFolder = new DropboxFileInfo() { Parent = dParent }; setupFileWithMetadata(newFolder, metadata); dParent.Contents.Add(nameKey, newFolder); return newFolder; }
private async Task<JToken> loadMetadata(string path, bool list = false, string hash = null) { var baseUrl = new StringBuilder(DropboxConfig.MetadataUrl); baseUrl.Append(DropboxConfig.AccessType); baseUrl.Append(path); var url = new ParamUrl(baseUrl.ToString()); if (list) url.Add("file_limit", "25000"); if (!list) url.Add("list", "false"); if (hash != null) url.Add("hash", hash); string response; try { response = await queryServer(url).ConfigureAwait(false); } catch (Exception e) { if(e.Message.Contains("(304)")) return null; else throw e; } return JToken.Parse(response); }
private async Task<DFileInfo> copyOperation(DropboxFileInfo file, DropboxFileInfo destFolder, bool move, string newName = null) { string nameKey = file.Name.ToLowerInvariant(); string newNameKey = (newName == null)? nameKey : newName.ToLowerInvariant(); // Storage provider should check possible file conflicts by itself, because // the outer system doesn't know how to access keys in dictionary correctly. if (destFolder.Contents.ContainsKey(newNameKey)) throw new FileConflictException("Entry with specified name is already present."); string path = concatenatePath(destFolder.Path, newName ?? file.Name); var url = new ParamUrl(move ? DropboxConfig.MoveUrl : DropboxConfig.CopyUrl); url.Add("root", DropboxConfig.AccessType); url.Add("from_path", percentEncoding(file.Path)); url.Add("to_path", percentEncoding(path)); var response = await queryServer(url).ConfigureAwait(false); var metadata = JObject.Parse(response); if (move) { file.Parent.Contents.Remove(nameKey); file.Parent = destFolder; setupFileWithMetadata(file, metadata); destFolder.Contents.Add(newNameKey, file); return file; } else { var newFile = (DropboxFileInfo)file.Clone(); newFile.Parent = destFolder; setupFileWithMetadata(newFile, metadata); destFolder.Contents.Add(newNameKey, newFile); return newFile; } }
private async Task<string> signAsync(ParamUrl url) { if (_oAuth == null) throw new ProviderNotSetupException("Please provide app key and secret first."); if (_accessToken == null) await retrieveAccessToken().ConfigureAwait(false); return _oAuth.Sign(url, _accessToken); }
private async Task<string> queryServer(ParamUrl url, string method = WebRequestMethods.Http.Get) { try { var signedUrl = await signAsync(url).ConfigureAwait(false); return await Http.ResponseToAsync(signedUrl, method); } catch (WebException e) { throw parseException(e); } }