Exemplo n.º 1
0
        // METADATA


        private void GetMetadata <T>(string dropboxPath, Action <DropboxRequestResult <T> > onResult) where T : DBXItem
        {
            var prms = new DropboxGetMetadataRequestParams(dropboxPath);

            Log("GetMetadata for " + dropboxPath);
            MakeDropboxRequest(METADATA_ENDPOINT, prms,
                               onResponse: (jsonStr) => {
                Log("GetMetadata onResponse");
                var dict = JSON.FromJson <Dictionary <string, object> >(jsonStr);

                if (typeof(T) == typeof(DBXFolder))
                {
                    var folderMetadata = DBXFolder.FromDropboxDictionary(dict);
                    onResult(new DropboxRequestResult <T>(folderMetadata as T));
                }
                else if (typeof(T) == typeof(DBXFile))
                {
                    var fileMetadata = DBXFile.FromDropboxDictionary(dict);
                    onResult(new DropboxRequestResult <T>(fileMetadata as T));
                }
            },
                               onProgress: null,
                               onWebError: (error) => {
                Log("GetMetadata:onWebError");
                onResult(DropboxRequestResult <T> .Error(error));
            });
        }
        // GETTING REMOTE CHANGES

        void FolderGetRemoteChanges(string dropboxFolderPath, Action <DropboxRequestResult <List <DBXFileChange> > > onResult, bool saveChangesInfoLocally = false)
        {
            GetFolderItems(dropboxFolderPath,
                           onResult: (res) => {
                if (res.error != null)
                {
                    onResult(DropboxRequestResult <List <DBXFileChange> > .Error(res.error));
                }
                else
                {
                    var fileChanges = new List <DBXFileChange>();

                    foreach (DBXFile remoteMetadata in res.data.Where(x => x.type == DBXItemType.File))
                    {
                        var localMetadata = GetLocalMetadataForFile(remoteMetadata.path);
                        if (localMetadata != null && !localMetadata.deletedOnRemote)
                        {
                            if (localMetadata.contentHash != remoteMetadata.contentHash)
                            {
                                fileChanges.Add(new DBXFileChange(remoteMetadata, DBXFileChangeType.Modified));
                            }
                        }
                        else
                        {
                            // no local metadata for this remote path - new object
                            fileChanges.Add(new DBXFileChange(remoteMetadata, DBXFileChangeType.Added));
                        }
                    }

                    // find other local files which were not in remote response (find deleted on remote files)
                    var processedDropboxFilePaths = res.data.Where(x => x.type == DBXItemType.File).Select(x => x.path).ToList();

                    //Log("Find all metadata paths");
                    var localDirectoryPath = GetPathInCache(dropboxFolderPath);
                    if (Directory.Exists(localDirectoryPath))
                    {
                        foreach (string localMetadataFilePath in Directory.GetFiles(localDirectoryPath, "*.dbxsync", SearchOption.AllDirectories))
                        {
                            var metadata    = ParseLocalMetadata(localMetadataFilePath);
                            var dropboxPath = metadata.path;
                            if (!processedDropboxFilePaths.Contains(dropboxPath) && !metadata.deletedOnRemote)
                            {
                                // wasnt in remote data - means removed
                                fileChanges.Add(new DBXFileChange(DBXFile.DeletedOnRemote(dropboxPath), DBXFileChangeType.Deleted));
                            }
                        }
                    }

                    if (saveChangesInfoLocally)
                    {
                        foreach (var fc in fileChanges)
                        {
                            SaveFileMetadata(fc.file);
                        }
                    }

                    onResult(new DropboxRequestResult <List <DBXFileChange> >(fileChanges));
                }
            }, recursive: true, onProgress: null);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Subscribes to file changes on Dropbox.
        /// Callback fires once, when change is being registered and changed file checksum is cached in local metadata.
        /// If change was made not during app runtime, callback fires as soon as app is running and checking for updates.
        /// Update interval can be changed using `DBXChangeForChangesIntervalSeconds` (default values if 5 seconds).
        /// </summary>
        /// <param name="dropboxFilePath">
        ///  Path to file on Dropbox or inside Dropbox App (depending on accessToken type).
        ///  Should start with "/". Example: /DropboxSyncExampleFolder/image.jpg
        /// </param>
        /// <param name="onChange">
        /// Callback function that receives `DBXFileChange` that contains `changeType` and `DBXFile` (updated file metadata).
        /// </param>
        public void SubscribeToFileChanges(string dropboxFilePath, Action <DBXFileChange> onChange)
        {
            var item = new DBXFile(dropboxFilePath);

            SubscribeToChanges(item, (changes) => {
                onChange(changes[0]);
            });
        }
Exemplo n.º 4
0
        void SaveFileMetadata(DBXFile fileMetadata)
        {
            var localFilePath = GetPathInCache(fileMetadata.path);

            // make sure containing directory exists
            var fileDirectoryPath = Path.GetDirectoryName(localFilePath);

            //Log("Local cached directory path: "+fileDirectoryPath);
            Directory.CreateDirectory(fileDirectoryPath);

            // write metadata to separate file near
            var newMetadataFilePath = GetMetadataFilePath(fileMetadata.path);

            File.WriteAllText(newMetadataFilePath, JsonUtility.ToJson(fileMetadata));
            //Log("Wrote metadata file "+newMetadataFilePath);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Moves file or folder from dropboxFromPath to dropboxToPath
        /// </summary>
        /// <param name="dropboxFromPath">From path</param>
        /// <param name="dropboxToPath">To path</param>
        /// <param name="onResult">Result callback containing metadata of moved object</param>
        public void Move(string dropboxFromPath, string dropboxToPath,
                         Action <DropboxRequestResult <DBXItem> > onResult)
        {
            var prms = new DropboxMoveFileRequestParams();

            prms.from_path = dropboxFromPath;
            prms.to_path   = dropboxToPath;

            MakeDropboxRequest(MOVE_ENDPOINT, prms, (jsonStr) => {
                DBXItem metadata = null;

                try {
                    var root          = JSON.FromJson <Dictionary <string, object> >(jsonStr);
                    var metadata_dict = root["metadata"] as Dictionary <string, object>;

                    if (metadata_dict[".tag"].ToString() == "file")
                    {
                        metadata = DBXFile.FromDropboxDictionary(metadata_dict);
                    }
                    else if (metadata_dict[".tag"].ToString() == "folder")
                    {
                        metadata = DBXFolder.FromDropboxDictionary(metadata_dict);
                    }
                }catch (Exception ex) {
                    _mainThreadQueueRunner.QueueOnMainThread(() => {
                        onResult(DropboxRequestResult <DBXItem> .Error(new DBXError(ex.Message, DBXErrorType.ParsingError)));
                    });
                    return;
                }

                _mainThreadQueueRunner.QueueOnMainThread(() => {
                    onResult(new DropboxRequestResult <DBXItem>(metadata));
                });
            }, onProgress: (progress) => {}, onWebError: (error) => {
                _mainThreadQueueRunner.QueueOnMainThread(() => {
                    if (error.ErrorType == DBXErrorType.RemotePathAlreadyExists)
                    {
                        error.ErrorDescription = "Can't move file: " + dropboxToPath + " already exists";
                    }
                    onResult(DropboxRequestResult <DBXItem> .Error(error));
                });
            });
        }
Exemplo n.º 6
0
        // FILE OPERATIONS

        /// <summary>
        /// Deletes file or folder on Dropbox
        /// </summary>
        /// <param name="dropboxPath">Path to file or folder on Dropbox or inside of Dropbox App folder (depending on accessToken type). Should start with "/". Example:/DropboxSyncExampleFolder/image.jpg</param>
        /// <param name="onResult">Callback function that receives DropboxRequestResult with DBXItem metadata of deleted file or folder</param>
        public void Delete(string dropboxPath, Action <DropboxRequestResult <DBXItem> > onResult)
        {
            var prms = new DropboxDeletePathRequestParams();

            prms.path = dropboxPath;

            MakeDropboxRequest(DELETE_ENDPOINT, prms, (jsonStr) => {
                DBXItem metadata = null;

                try {
                    var root          = JSON.FromJson <Dictionary <string, object> >(jsonStr);
                    var metadata_dict = root["metadata"] as Dictionary <string, object>;

                    if (metadata_dict[".tag"].ToString() == "file")
                    {
                        metadata = DBXFile.FromDropboxDictionary(metadata_dict);
                    }
                    else if (metadata_dict[".tag"].ToString() == "folder")
                    {
                        metadata = DBXFolder.FromDropboxDictionary(metadata_dict);
                    }
                }catch (Exception ex) {
                    _mainThreadQueueRunner.QueueOnMainThread(() => {
                        onResult(DropboxRequestResult <DBXItem> .Error(new DBXError(ex.Message, DBXErrorType.ParsingError)));
                    });
                    return;
                }

                _mainThreadQueueRunner.QueueOnMainThread(() => {
                    onResult(new DropboxRequestResult <DBXItem>(metadata));
                });
            }, onProgress: (progress) => {}, onWebError: (error) => {
                _mainThreadQueueRunner.QueueOnMainThread(() => {
                    onResult(DropboxRequestResult <DBXItem> .Error(error));
                });
            });
        }
 void UpdateFileFromRemote(DBXFile dropboxFile, Action onSuccess, Action <float> onProgress, Action <DBXError> onError)
 {
     UpdateFileFromRemote(dropboxFile.path, onSuccess, onProgress, onError);
 }
 public DBXFileChange(DBXFile f, DBXFileChangeType c)
 {
     file       = f;
     changeType = c;
 }
        void MakeDropboxUploadRequest(string url, byte[] dataToUpload, string jsonParameters,
                                      Action <DBXFile> onResponse, Action <float> onProgress, Action <DBXError> onWebError)
        {
            DropboxSyncUtils.IsOnlineAsync((isOnline) => {
                if (!isOnline)
                {
                    onWebError(new DBXError("No internet connection", DBXErrorType.NetworkProblem));
                    return;
                }

                try {
                    using (var client = new DBXWebClient()){
                        client.Headers.Set("Authorization", "Bearer " + DropboxAccessToken);
                        client.Headers.Set("Dropbox-API-Arg", jsonParameters);
                        client.Headers.Set("Content-Type", "application/octet-stream");



                        client.UploadProgressChanged += (s, e) => {
                            Log(string.Format("Upload {0} bytes out of {1} ({2}%)", e.BytesSent, e.TotalBytesToSend, e.ProgressPercentage));

                            if (onProgress != null)
                            {
                                // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                var uploadProgress = (float)e.BytesSent / e.TotalBytesToSend;

                                var SERVER_PROCESSING_PERCENTAG_VALUE = 0.99f;

                                if (uploadProgress > SERVER_PROCESSING_PERCENTAG_VALUE && e.ProgressPercentage < 100)
                                {
                                    // waiting for server to process uploaded file
                                    onProgress(SERVER_PROCESSING_PERCENTAG_VALUE);
                                }
                                else
                                {
                                    onProgress(uploadProgress);
                                }
                                // });
                            }
                        };

                        client.UploadDataCompleted += (s, e) => {
                            Log("MakeDropboxUploadRequest -> UploadDataCompleted");
                            _activeWebClientsList.Remove(client);

                            if (e.Error != null)
                            {
                                Log("MakeDropboxUploadRequest -> UploadDataCompleted -> with error");

                                if (e.Error is WebException)
                                {
                                    Log("MakeDropboxUploadRequest -> UploadDataCompleted -> with error -> WebException");
                                    var webex       = e.Error as WebException;
                                    var stream      = webex.Response.GetResponseStream();
                                    var reader      = new StreamReader(stream);
                                    var responseStr = reader.ReadToEnd();
                                    LogWarning(responseStr);

                                    try{
                                        var dict         = JSON.FromJson <Dictionary <string, object> >(responseStr);
                                        var errorSummary = dict["error_summary"].ToString();
                                        // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                        onWebError(new DBXError(errorSummary, DBXErrorType.DropboxAPIError));
                                        // });
                                    }catch {
                                        // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                        onWebError(new DBXError(e.Error.Message, DBXErrorType.ParsingError));
                                        // });
                                    }
                                }
                                else
                                {
                                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                    Log("e.Error is something else");
                                    if (e.Error != null)
                                    {
                                        onWebError(new DBXError(e.Error.Message, DBXErrorType.Unknown));
                                    }
                                    else
                                    {
                                        onWebError(new DBXError("Unknown error", DBXErrorType.Unknown));
                                    }

                                    // });
                                }
                            }
                            else if (e.Cancelled)
                            {
                                Log("MakeDropboxUploadRequest -> canceled");
                                // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                onWebError(new DBXError("Download was cancelled.", DBXErrorType.UserCancelled));
                                // });
                            }
                            else
                            {
                                Log("MakeDropboxUploadRequest -> no error");
                                //var respStr = Encoding.UTF8.GetString(e.Result);
                                var metadataJsonStr = Encoding.UTF8.GetString(e.Result);;
                                Log(metadataJsonStr);
                                var dict         = JSON.FromJson <Dictionary <string, object> >(metadataJsonStr);
                                var fileMetadata = DBXFile.FromDropboxDictionary(dict);

                                // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                onResponse(fileMetadata);
                                // });
                            }
                        };

                        var uri = new Uri(url);

                        // don't use UploadFile (https://stackoverflow.com/questions/18539807/how-to-remove-multipart-form-databoundary-from-webclient-uploadfile)
                        client.UploadDataAsync(uri, "POST", dataToUpload);
                        _activeWebClientsList.Add(client);
                    }
                } catch (WebException ex) {
                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                    onWebError(new DBXError(ex.Message, DBXErrorType.Unknown));
                    // });
                }
            });
        }
        void MakeDropboxDownloadRequest(string url, string jsonParameters,
                                        Action <DBXFile, byte[]> onResponse, Action <float> onProgress, Action <DBXError> onWebError)
        {
            DropboxSyncUtils.IsOnlineAsync((isOnline) => {
                if (!isOnline)
                {
                    onWebError(new DBXError("No internet connection", DBXErrorType.NetworkProblem));
                    return;
                }

                try {
                    using (var client = new DBXWebClient()){
                        client.Headers.Set("Authorization", "Bearer " + DropboxAccessToken);
                        client.Headers.Set("Dropbox-API-Arg", jsonParameters);

                        client.DownloadProgressChanged += (s, e) => {
                            if (onProgress != null)
                            {
                                //Log(string.Format("Downloaded {0} bytes out of {1} ({2}%)", e.BytesReceived, e.TotalBytesToReceive, e.ProgressPercentage));
                                if (e.TotalBytesToReceive != -1)
                                {
                                    // if download size in known from server
                                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                    onProgress((float)e.BytesReceived / e.TotalBytesToReceive);
                                    // });
                                }
                                else
                                {
                                    // return progress is going but unknown
                                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                    onProgress(-1);
                                    // });
                                }
                            }
                        };



                        client.DownloadDataCompleted += (s, e) => {
                            _activeWebClientsList.Remove(client);

                            if (e.Error != null)
                            {
                                if (e.Error is WebException)
                                {
                                    var webex       = e.Error as WebException;
                                    var stream      = webex.Response.GetResponseStream();
                                    var reader      = new StreamReader(stream);
                                    var responseStr = reader.ReadToEnd();
                                    Log(responseStr);

                                    try{
                                        var dict         = JSON.FromJson <Dictionary <string, object> >(responseStr);
                                        var errorSummary = dict["error_summary"].ToString();
                                        // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                        onWebError(new DBXError(errorSummary, DBXError.DropboxAPIErrorSummaryToErrorType(errorSummary)));
                                        // });
                                    }catch {
                                        // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                        onWebError(new DBXError(e.Error.Message, DBXErrorType.ParsingError));
                                        // });
                                    }
                                }
                                else
                                {
                                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                    Log("e.Error is something else");
                                    if (e.Error != null)
                                    {
                                        onWebError(new DBXError(e.Error.Message, DBXErrorType.Unknown));
                                    }
                                    else
                                    {
                                        onWebError(new DBXError("Unknown error", DBXErrorType.Unknown));
                                    }
                                    // });
                                }
                            }
                            else if (e.Cancelled)
                            {
                                // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                onWebError(new DBXError("Download was cancelled.", DBXErrorType.UserCancelled));
                                // });
                            }
                            else
                            {
                                //var respStr = Encoding.UTF8.GetString(e.Result);
                                var metadataJsonStr = client.ResponseHeaders["Dropbox-API-Result"].ToString();
                                Log(metadataJsonStr);
                                var dict         = JSON.FromJson <Dictionary <string, object> >(metadataJsonStr);
                                var fileMetadata = DBXFile.FromDropboxDictionary(dict);

                                // _mainThreadQueueRunner.QueueOnMainThread(() => {
                                onResponse(fileMetadata, e.Result);
                                // });
                            }
                        };

                        var uri = new Uri(url);
                        client.DownloadDataAsync(uri);
                        _activeWebClientsList.Add(client);
                    }
                } catch (WebException ex) {
                    // _mainThreadQueueRunner.QueueOnMainThread(() => {
                    onWebError(new DBXError(ex.Message, DBXErrorType.Unknown));
                    // });
                }
            });
        }
        void FileGetRemoteChanges(string dropboxFilePath, Action <DBXFileChange> onResult,
                                  Action <DBXError> onError, bool saveChangesInfoLocally = false)
        {
            var localFilePath   = GetPathInCache(dropboxFilePath);
            var localFileExists = File.Exists(localFilePath);

            var metadataFilePath = GetMetadataFilePath(dropboxFilePath);
            var localMetadata    = GetLocalMetadataForFile(dropboxFilePath);

            // request for metadata to get remote content hash
            //Log("Getting metadata");
            GetMetadata <DBXFile>(dropboxFilePath, onResult: (res) => {
                DBXFileChange result = null;

                if (res.error != null)
                {
                    Log("Failed to get remote metadata for file " + dropboxFilePath);
                    if (res.error.ErrorType == DBXErrorType.RemotePathNotFound)
                    {
                        Log("file not found - file was deleted or moved");
                        // file was deleted or moved

                        // if we knew about this file before
                        if (localMetadata != null)
                        {
                            // if we didnt know that it was removed
                            if (!localMetadata.deletedOnRemote)
                            {
                                result = new DBXFileChange(DBXFile.DeletedOnRemote(dropboxFilePath), DBXFileChangeType.Deleted);
                            }
                            else
                            {
                                // no change
                                result = new DBXFileChange(localMetadata, DBXFileChangeType.None);
                            }
                        }
                        else
                        {
                            onError(res.error);
                        }
                    }
                    else
                    {
                        onError(res.error);
                        return;
                    }
                }
                else
                {
                    Log("Got remote metadata for file " + dropboxFilePath);
                    var remoteMedatadata = res.data;

                    if (localMetadata != null && !localMetadata.deletedOnRemote)
                    {
                        Log("local metadata file exists and we knew this file existed on remote");
                        Log("check if remote content has changed");
                        // get local content hash
                        // var local_content_hash = localMetadata.contentHash;
                        string local_content_hash = null;
                        if (localFileExists)
                        {
                            local_content_hash = DropboxSyncUtils.GetDropboxContentHashForFile(localFilePath);
                        }
                        else
                        {
                            local_content_hash = localMetadata.contentHash;
                        }

                        var remote_content_hash = remoteMedatadata.contentHash;

                        if (local_content_hash != remote_content_hash)
                        {
                            Log("remote content hash has changed - file was modified");
                            result = new DBXFileChange(remoteMedatadata, DBXFileChangeType.Modified);
                        }
                        else
                        {
                            Log("remote content did not change");
                            result = new DBXFileChange(remoteMedatadata, DBXFileChangeType.None);
                        }
                    }
                    else
                    {
                        // metadata file doesnt exist
                        Log("local metadata file doesnt exist - consider as new file added");
                        // TODO: check maybe file itself exists and right version, then just create metadata file - no need to redownload file itself
                        result = new DBXFileChange(remoteMedatadata, DBXFileChangeType.Added);
                    }
                }

                // if no error
                if (result != null)
                {
                    if (saveChangesInfoLocally)
                    {
                        SaveFileMetadata(result.file);
                    }

                    onResult(result);
                }
            });
        }
        void _GetFolderItemsFlat(string folderPath, Action <List <DBXItem> > onResult, Action <float> onProgress,
                                 Action <DBXError> onError, bool recursive = false, string requestCursor = null, List <DBXItem> currentResults = null)
        {
            folderPath = DropboxSyncUtils.NormalizePath(folderPath);

            if (folderPath == "/")
            {
                folderPath = "";                 // dropbox error fix
            }

            string url;
            DropboxRequestParams prms;

            if (requestCursor == null)
            {
                // first request
                currentResults = new List <DBXItem>();
                url            = LIST_FOLDER_ENDPOINT;
                prms           = new DropboxListFolderRequestParams {
                    path = folderPath, recursive = recursive
                };
            }
            else
            {
                // have cursor to continue list
                url  = LIST_FOLDER_CONTINUE_ENDPOINT;
                prms = new DropboxContinueWithCursorRequestParams(requestCursor);
            }

            MakeDropboxRequest(url, prms, onResponse: (jsonStr) => {
                //Log("Got reponse: "+jsonStr);

                Dictionary <string, object> root = null;
                try {
                    root = JSON.FromJson <Dictionary <string, object> >(jsonStr);
                }catch (Exception ex) {
                    onError(new DBXError(ex.Message, DBXErrorType.ParsingError));
                    return;
                }

                var entries = root["entries"] as List <object>;
                foreach (Dictionary <string, object> entry in entries)
                {
                    if (entry[".tag"].ToString() == "file")
                    {
                        currentResults.Add(DBXFile.FromDropboxDictionary(entry));
                    }
                    else if (entry[".tag"].ToString() == "folder")
                    {
                        currentResults.Add(DBXFolder.FromDropboxDictionary(entry));
                    }
                    else
                    {
                        onError(new DBXError("Unknown entry tag " + entry[".tag".ToString()], DBXErrorType.Unknown));
                        return;
                    }
                }

                if ((bool)root["has_more"])
                {
                    // recursion
                    _GetFolderItemsFlat(folderPath, onResult, onProgress, onError, recursive: recursive,
                                        requestCursor: root["cursor"].ToString(),
                                        currentResults: currentResults);
                }
                else
                {
                    // done
                    onResult(currentResults);
                }
            }, onProgress: onProgress,
                               onWebError: (webErrorStr) => {
                //LogError("Got web err: "+webErrorStr);
                onError(webErrorStr);
            });
        }