/// <summary> /// Creates folder using path specified /// </summary> /// <param name="dropboxFolderPath">Path of folder to create</param> /// <param name="onResult">Result callback that contains metadata of the created folder</param> public void CreateFolder(string dropboxFolderPath, Action <DropboxRequestResult <DBXFolder> > onResult) { var path = DropboxSyncUtils.NormalizePath(dropboxFolderPath); var prms = new DropboxCreateFolderRequestParams(); prms.path = path; MakeDropboxRequest(CREATE_FOLDER_ENDPOINT, prms, (jsonStr) => { DBXFolder folderMetadata = null; try { var root = JSON.FromJson <Dictionary <string, object> >(jsonStr); folderMetadata = DBXFolder.FromDropboxDictionary(root["metadata"] as Dictionary <string, object>); }catch (Exception ex) { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <DBXFolder> .Error(new DBXError(ex.Message, DBXErrorType.ParsingError))); }); return; } _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <DBXFolder>(folderMetadata)); }); }, onProgress: (progress) => {}, onWebError: (error) => { if (error.ErrorDescription.Contains("path/conflict/folder")) { error.ErrorType = DBXErrorType.RemotePathAlreadyExists; } _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <DBXFolder> .Error(error)); }); }); }
/// <summary> /// Unsubscribe specific callback from changes on specified Dropbox path /// </summary> /// <param name="dropboxPath">Path from which to unsubscribe</param> /// <param name="onChange">Callback reference</param> public void UnsubscribeFromChangesOnPath(string dropboxPath, Action <List <DBXFileChange> > onChange) { dropboxPath = DropboxSyncUtils.NormalizePath(dropboxPath); var item = OnChangeCallbacksDict.Where(p => p.Key.path == dropboxPath).Select(p => p.Key).FirstOrDefault(); if (item != null) { OnChangeCallbacksDict[item].Remove(onChange); } }
/// <summary> /// Unsubscribes all subscribers from changes on specified Dropbox path /// </summary> /// <param name="dropboxPath">Path from which to unsubscribe</param> public void UnsubscribeAllFromChangesOnPath(string dropboxPath) { dropboxPath = DropboxSyncUtils.NormalizePath(dropboxPath); var removeKeys = OnChangeCallbacksDict.Where(p => p.Key.path == dropboxPath).Select(p => p.Key).ToList(); foreach (var k in removeKeys) { OnChangeCallbacksDict.Remove(k); } }
/// <summary> /// Retrieves structure of dropbox folders and files inside specified folder. /// </summary> /// <param name="dropboxFolderPath">Dropbox folder path</param> /// <param name="onResult">Callback function that receives result containing DBXFolder with all child nodes inside.</param> /// <param name="onProgress">Callback fnction that receives float from 0 to 1 intdicating the progress.</param> public void GetFolderStructure(string dropboxFolderPath, Action <DropboxRequestResult <DBXFolder> > onResult, Action <float> onProgress = null) { var path = DropboxSyncUtils.NormalizePath(dropboxFolderPath); _GetFolderItemsFlat(path, onResult: (items) => { DBXFolder rootFolder = null; // get root folder if (path == "/") { rootFolder = new DBXFolder { id = "", path = "/", name = "", items = new List <DBXItem>() }; } else { rootFolder = items.Where(x => x.path == path).First() as DBXFolder; } // squash flat results rootFolder = BuildStructureFromFlat(rootFolder, items); _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <DBXFolder>(rootFolder)); }); }, onProgress: (progress) => { if (onProgress != null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onProgress(progress); }); } }, onError: (errorStr) => { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <DBXFolder> .Error(errorStr)); }); }, recursive: true); }
void Update() { _internetConnectionWatcher.Update(); _mainThreadQueueRunner.PerformQueuedTasks(); // check remote changes for subscribed if (Time.unscaledTime - _lastTimeCheckedForSubscribedItemsChanges > CHECK_REMOTE_UPDATES_INTERVAL_SECONDS) { DropboxSyncUtils.IsOnlineAsync((isOnline) => { if (isOnline) { try { CheckChangesForSubscribedItems(); }catch (Exception ex) { Debug.LogException(ex); } } }); _lastTimeCheckedForSubscribedItemsChanges = Time.unscaledTime; } }
DBXFolder BuildStructureFromFlat(DBXFolder rootFolder, List <DBXItem> pool) { foreach (var poolItem in pool) { // if item is immediate child of rootFolder if (DropboxSyncUtils.IsPathImmediateChildOfFolder(rootFolder.path, poolItem.path)) { // add poolItem to folder children if (poolItem.type == DBXItemType.Folder) { //Debug.Log("Build structure recursive"); rootFolder.items.Add(BuildStructureFromFlat(poolItem as DBXFolder, pool)); } else { rootFolder.items.Add(poolItem); } //Debug.Log("Added child "+poolItem.path); } } return(rootFolder); }
public DBXFolder(string p) { type = DBXItemType.Folder; path = DropboxSyncUtils.NormalizePath(p); }
public DBXFile(string p) { type = DBXItemType.File; path = DropboxSyncUtils.NormalizePath(p); }
// GETTING FILE /// <summary> /// Asynchronously retrieves file from Dropbox and tries to produce object of specified type T. /// </summary> /// <param name="dropboxPath">Path to file on Dropbox or inside of Dropbox App folder (depending on accessToken type). Should start with "/". Example: /DropboxSyncExampleFolder/image.jpg</param> /// <param name="onResult">Result callback</param> /// <param name="onProgress">Callback function that receives progress as float from 0 to 1.</param> /// <param name="useCachedFirst">If True then first tries to get data from cache, if not cached then downloads.</param> /// <param name="useCachedIfOffline">If True and there's no Internet connection then retrieves file from cache if cached, otherwise produces error.</param> /// <param name="receiveUpdates">If True, then when there are remote updates on Dropbox, callback function onResult will be triggered again with updated version of the file.</param> public void GetFile <T>(string dropboxPath, Action <DropboxRequestResult <T> > onResult, Action <float> onProgress = null, bool useCachedFirst = false, bool useCachedIfOffline = true, bool receiveUpdates = false) where T : class { Action <DropboxRequestResult <byte[]> > onResultMiddle = null; if (typeof(T) == typeof(string)) { //Log("GetFile: text type"); // TEXT DATA onResultMiddle = (res) => { if (res.error != null || res.data == null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <T> .Error(res.error)); }); } else { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <T>(DropboxSyncUtils.GetAutoDetectedEncodingStringFromBytes(res.data) as T)); }); } }; } else if (typeof(T) == typeof(JsonObject) || typeof(T) == typeof(JsonArray)) { //Log("GetFile: JSON type"); // JSON OBJECT/ARRAY onResultMiddle = (res) => { if (res.error != null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <T> .Error(res.error)); }); } else { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <T>(JSON.FromJson <T>( DropboxSyncUtils.GetAutoDetectedEncodingStringFromBytes(res.data) ))); }); } }; } else if (typeof(T) == typeof(Texture2D)) { //Log("GetFile: Texture2D type"); // IMAGE DATA onResultMiddle = (res) => { if (res.error != null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <T> .Error(res.error)); }); } else { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <T>(DropboxSyncUtils.LoadImageToTexture2D(res.data) as T)); }); } }; } else { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <T> .Error( new DBXError(string.Format("Dont have a mapping byte[] -> {0}. Type {0} is not supported.", typeof(T).ToString()), DBXErrorType.NotSupported ) ) ); }); return; } GetFileAsBytes(dropboxPath, onResultMiddle, onProgress, useCachedFirst, useCachedIfOffline, receiveUpdates); }
/// <summary> /// Asynchronously retrieves file from Dropbox as byte[] /// </summary> /// <param name="dropboxPath">Path to file on Dropbox or inside of Dropbox App folder (depending on accessToken type). Should start with "/". Example: /DropboxSyncExampleFolder/image.jpg</param> /// <param name="onResult">Result callback</param> /// <param name="onProgress">Callback function that receives progress as float from 0 to 1.</param> /// <param name="useCachedFirst">If True then first tries to get data from cache, if not cached then downloads.</param> /// <param name="useCachedIfOffline">If True and there's no Internet connection then retrieves file from cache if cached, otherwise produces error.</param> /// <param name="receiveUpdates">If true , then when there are remote updates on Dropbox, callback function onResult will be triggered again with updated version of the file.</param> public void GetFileAsBytes(string dropboxPath, Action <DropboxRequestResult <byte[]> > onResult, Action <float> onProgress = null, bool useCachedFirst = false, bool useCachedIfOffline = true, bool receiveUpdates = false) { if (DropboxSyncUtils.IsBadDropboxPath(dropboxPath)) { onResult(DropboxRequestResult <byte[]> .Error( new DBXError("Cant get file: bad path " + dropboxPath, DBXErrorType.BadRequest) ) ); return; } Action returnCachedResult = () => { var cachedFilePath = GetPathInCache(dropboxPath); if (File.Exists(cachedFilePath)) { var bytes = File.ReadAllBytes(cachedFilePath); _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(new DropboxRequestResult <byte[]>(bytes)); }); } else { Log("cache doesnt have file"); _mainThreadQueueRunner.QueueOnMainThread(() => { onResult( DropboxRequestResult <byte[]> .Error( new DBXError("File " + dropboxPath + " is removed on remote", DBXErrorType.RemotePathNotFound) ) ); }); } }; Action subscribeToUpdatesAction = () => { SubscribeToFileChanges(dropboxPath, (fileChange) => { UpdateFileFromRemote(dropboxPath, onSuccess: () => { // return updated cached result returnCachedResult(); }, onProgress: (progress) => { if (onProgress != null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onProgress(progress); }); } }, onError: (error) => { _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <byte[]> .Error(error)); }); }); }); }; // maybe no need to do any remote requests if ((useCachedFirst) && IsFileCached(dropboxPath)) { Log("GetFile: using cached version"); returnCachedResult(); if (receiveUpdates) { subscribeToUpdatesAction(); } } else { //Log("GetFile: check if online"); // now check if we online DropboxSyncUtils.IsOnlineAsync((isOnline) => { try { if (isOnline) { Log("GetFile: internet available"); // check if have updates and load them UpdateFileFromRemote(dropboxPath, onSuccess: () => { Log("GetFile: state of dropbox file is " + dropboxPath + " is synced now"); // return updated cached result returnCachedResult(); if (receiveUpdates) { subscribeToUpdatesAction(); } }, onProgress: (progress) => { if (onProgress != null) { _mainThreadQueueRunner.QueueOnMainThread(() => { onProgress(progress); }); } }, onError: (error) => { //Log("error"); _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <byte[]> .Error(error)); }); if (receiveUpdates) { subscribeToUpdatesAction(); } }); } else { Log("GetFile: internet not available"); if (useCachedIfOffline && IsFileCached(dropboxPath)) { Log("GetFile: cannot check for updates - using cached version"); returnCachedResult(); if (receiveUpdates) { subscribeToUpdatesAction(); } } else { if (receiveUpdates) { // try again when internet recovers _internetConnectionWatcher.SubscribeToInternetConnectionRecoverOnce(() => { GetFileAsBytes(dropboxPath, onResult, onProgress, useCachedFirst, useCachedIfOffline, receiveUpdates); }); subscribeToUpdatesAction(); } else { // error _mainThreadQueueRunner.QueueOnMainThread(() => { onResult(DropboxRequestResult <byte[]> .Error( new DBXError("GetFile: No internet connection", DBXErrorType.NetworkProblem) ) ); }); } } } }catch (Exception ex) { Debug.LogException(ex); } }); } }
void MakeDropboxRequest(string url, string jsonParameters, Action <string> onResponse, Action <float> onProgress, Action <DBXError> onWebError) { Log("MakeDropboxRequest url: " + url); 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("Content-Type", "application/json"); client.DownloadProgressChanged += (s, e) => { if (onProgress != null) { Log(string.Format("Downloaded {0} bytes out of {1}", e.BytesReceived, e.TotalBytesToReceive)); 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.UploadDataCompleted += (s, e) => { Log("MakeDropboxRequest -> UploadDataCompleted"); _activeWebClientsList.Remove(client); if (e.Error != null) { Log("MakeDropboxRequest -> UploadDataCompleted -> Error"); //LogError("MakeDropboxRequest -> UploadDataCompleted -> Error "+e.Error.Message); if (e.Error is WebException) { Log("MakeDropboxRequest -> UploadDataCompleted -> Error -> WebException"); var webex = e.Error as WebException; try{ var stream = webex.Response.GetResponseStream(); var reader = new StreamReader(stream); var responseStr = reader.ReadToEnd(); var dict = JSON.FromJson <Dictionary <string, object> >(responseStr); var errorSummary = dict["error_summary"].ToString(); // _mainThreadQueueRunner.QueueOnMainThread(() => { onWebError(new DBXError(errorSummary, DBXError.DropboxAPIErrorSummaryToErrorType(errorSummary))); // }); }catch (Exception ex) { Log("MakeDropboxRequest -> UploadDataCompleted -> Error -> WebException -> try get summary -> Exception: " + ex.Message); // _mainThreadQueueRunner.QueueOnMainThread(() => { onWebError(new DBXError(e.Error.Message, DBXErrorType.ParsingError)); // }); } } else { // _mainThreadQueueRunner.QueueOnMainThread(() => { Log("MakeDropboxRequest -> UploadDataCompleted -> Error -> not WebException"); if (e.Error != null) { onWebError(new DBXError(e.Error.Message + "\n" + e.Error.StackTrace, DBXErrorType.Unknown)); } else { onWebError(new DBXError("Unknown error", DBXErrorType.Unknown)); } // }); } } else if (e.Cancelled) { onWebError(new DBXError("User canceled request", DBXErrorType.UserCancelled)); } else { // no error var respStr = Encoding.UTF8.GetString(e.Result); // _mainThreadQueueRunner.QueueOnMainThread(() => { onResponse(respStr); // }); } }; var uri = new Uri(url); Log("MakeDropboxRequest:client.UploadDataAsync"); client.UploadDataAsync(uri, "POST", Encoding.Default.GetBytes(jsonParameters)); _activeWebClientsList.Add(client); } } catch (Exception ex) { //onWebError(ex.Message); //Log("caught exeption"); onWebError(new DBXError(ex.Message, DBXErrorType.Unknown)); //Log(ex.Response.ToString()); } }); }
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); }); }