예제 #1
0
        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();
        }
예제 #2
0
        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;
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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;
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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;
        }
예제 #7
0
        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);
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
 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);
 }
예제 #10
0
 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);
     }            
 }