├── .gitignore ├── .gitlab-ci.yml ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── Makefile ├── README.adoc ├── TODO ├── src ├── client.rs ├── files.rs ├── lib.rs ├── sharing.rs ├── structs.rs └── users.rs └── tags /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | build: 2 | script: 3 | - cargo build --verbose --release 4 | tags: 5 | - rust 6 | pages: 7 | stage: deploy 8 | script: 9 | - cargo doc --verbose 10 | - mkdir -p public/ 11 | - cp -r target/doc/* public/ 12 | artifacts: 13 | paths: 14 | - public 15 | only: 16 | - master 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: rust 3 | rust: 4 | - nightly 5 | - beta 6 | - stable 7 | matrix: 8 | allow_failures: 9 | - rust: nightly 10 | before_script: 11 | - | 12 | pip install travis-cargo --user && 13 | export PATH=$HOME/.local/bin:$PATH 14 | script: 15 | - | 16 | travis-cargo build && 17 | travis-cargo --only stable doc 18 | addons: 19 | apt: 20 | packages: 21 | - libcurl4-openssl-dev 22 | - libelf-dev 23 | - libdw-dev 24 | after_success: 25 | - travis-cargo --only stable doc-upload 26 | notifications: 27 | email: 28 | on_success: never 29 | env: 30 | global: 31 | - TRAVIS_CARGO_NIGHTLY_FEATURE="" 32 | - secure: Gdck27DP9wI+wPUIUMsrPL4N4HoYAd/H0S/yrN8+KhrsSH3vqHR4QblrKgNZuV9IdGQzfxVEX8MaV+O4fcH3ePz4hm5YNz6VS+fXYgRbbzzaPhXYqP8AVqb+RCGW8ecyf9957NLW5EYSnJfqjZCkyQf47BO/reSO6Fso9noIBX+IqAn2eogh/we7JSIDqp7Tvn6aKd781Wep5E8cDL3F9pFBSSSgKunT72HohoyPclVoSZe0L+ib5r7hW0g3teOiEQJDT3aibJWRoRAblq4keOep7CfZMP6QpSyA44CFa+51k2vCG/1k8m72HM5P+df2BMQl1+euk9LB0oxI+GDtETGLB28DXnomr58pa/YtBFuUUTM9KGJ/GZ/ONmB1WvFn6/lTSukMfRMbdINuPHhKhoZ/m3vee53h3TO7w4kZgC22p3TS6xmQXLsBfZ5ZOnMVctaf283io5Iw5IVgZ/E0aF8eyzRGTPUyGyYiPByJEjOWymwrCLGxcDVM3i4fHqgqOf6AXrHjTNmE71ado8NzKHKhsbDNVSudAMGio4vOpTK66eewM2NSQq4nre+lIgTGFPZ2JQvBaAtaywWRFg+ym79zgw0K/I3RP7Rxxs7Y32kzW2VNAagFgla5WC0ml5785Z1e/t3yrN6thHJ0zNkjGBB0ABHLMPlUVarnzW9ftlg= 33 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dbox" 3 | version = "0.1.3" 4 | authors = ["Paul Woolcock "] 5 | license = "MIT/Apache-2.0" 6 | readme = "README.adoc" 7 | description = """ 8 | An unofficial Dropbox SDK 9 | """ 10 | repository = "https://gitlab.com/pwoolcoc/dbox.git" 11 | homepage = "https://pwoolcoc.gitlab.io/dbox/dbox/" 12 | 13 | [features] 14 | default = ["hyper-client"] 15 | hyper-client = ["hyper"] 16 | 17 | [dependencies] 18 | hyper = { version = "~0.7.2", optional = true } 19 | chrono = "~0.2.17" 20 | rustc-serialize = "~0.3" 21 | 22 | [dev-dependencies] 23 | rand = "~0.3.12" 24 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(shell ls ./src/*.rs) 2 | 3 | tags: $(SOURCE) 4 | ctags -f tags --options=$(HOME)/code/rust/src/etc/ctags.rust --recurse ./src/ 5 | 6 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Unofficial Dropbox SDK for Rust 2 | 3 | image:https://gitlab.com/pwoolcoc/dbox/badges/master/build.svg["Build Status", link="https://gitlab.com/pwoolcoc/dbox"] 4 | 5 | This is an (unofficial, as in not endorsed by) Dropbox SDK for 6 | https://rust-lang.org[Rust]. At present it is not complete, though the API is 7 | mostly fleshed out. 8 | 9 | Currently it uses https://hyperium.github.io[Hyper] to communicate with the 10 | Dropbox API, but this is swappable, to allow a user to use their preferred HTTP 11 | library, or use more advanced features. 12 | 13 | It is also very much lacking in tests and documentation. 14 | 15 | == What's working 16 | 17 | Right now the following API calls are available: 18 | 19 | - `/files/copy` 20 | - `/files/create_folder` 21 | - `/files/delete` 22 | - `/files/download` 23 | - `/files/list_folder` 24 | - `/files/upload` 25 | - `/files/get_metadata` 26 | - `/files/move` 27 | 28 | == Examples 29 | 30 | 31 | [source,rust] 32 | .Basic example 33 | ---- 34 | extern crate dbox; 35 | 36 | use dbox::client::Client; 37 | use dbox::files; 38 | 39 | const ACCESS_TOKEN: &'static str = "MY_ACCESS_TOKEN"; 40 | 41 | fn main() { 42 | let client = Client::new(ACCESS_TOKEN); 43 | let (metadata, response) = files::download(&client, "/path/to/file").unwrap(); 44 | } 45 | ---- 46 | 47 | 48 | [source,rust] 49 | .With non-Hyper client 50 | ---- 51 | // compile with `cargo build --no-default-features` 52 | extern crate dbox; 53 | extern crate rustc_serialize; 54 | 55 | use dbox::{DropboxClient, Result, Response}; 56 | use dbox::files; 57 | 58 | struct MyClient; 59 | 60 | impl DropboxClient for MyClient { 61 | fn access_token() -> &str { 62 | // return access token 63 | } 64 | 65 | fn request(&self, url: &str, headers: &mut BTreeMap, body: &T) -> Result 66 | where T: rustc_serialize::Encodable + Clone 67 | { 68 | // implement http request here 69 | } 70 | } 71 | 72 | fn main() { 73 | let client = MyClient; 74 | let (metadata, response) = files::download(&client, "/path/to/file").unwrap(); 75 | } 76 | ---- 77 | 78 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * All the API functions are stubbed out, now they just need to be filled in 2 | with details, so they actually do what they are supposed to. 3 | * Need to make sure the correct errors are getting returned. 4 | * Need to back through and fix all occurences of the `Metadata` type to be what 5 | it is actually supposed to be. Here are all the `Metadata` types I have 6 | encountered so far: 7 | 8 | * FileMetadata 9 | * FolderMetadata 10 | * PathLinkMetadata 11 | * SharedFolderMetadata 12 | * LinkMetadata 13 | * more? 14 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use super::{ApiError, Result, Response, Endpoint, DropboxClient}; 2 | use hyper::client as hyper_client; 3 | use hyper::error as hyper_error; 4 | use hyper::header::{Headers, Authorization, Bearer, ContentType}; 5 | use hyper::mime::{Mime, TopLevel, SubLevel}; 6 | use hyper::status::StatusCode; 7 | use hyper::http::RawStatus; 8 | use std::io::Read; 9 | use std::collections::BTreeMap; 10 | use std::fmt; 11 | use rustc_serialize; 12 | use rustc_serialize::json; 13 | 14 | #[derive(Debug, Clone, PartialEq)] 15 | pub struct Client { 16 | token: String, 17 | user_agent: String, 18 | proxies: Vec, 19 | max_retries: u32, 20 | max_connections: u32, 21 | } 22 | 23 | impl Client { 24 | pub fn new(token: &str) -> Result { 25 | if token.len() < 62 { 26 | Err(ApiError::TokenError) 27 | } else { 28 | Ok(Client { 29 | token: token.to_owned(), 30 | proxies: vec![], 31 | user_agent: "Dropbox SDK/Rust".to_owned(), 32 | max_retries: 4, 33 | max_connections: 8, 34 | }) 35 | } 36 | } 37 | 38 | pub fn user_agent(self, user_agent: &str) -> Client { 39 | Client { 40 | user_agent: user_agent.to_owned(), 41 | .. self 42 | } 43 | } 44 | 45 | pub fn max_retries(self, max_retries: u32) -> Client { 46 | Client { 47 | max_retries: max_retries, 48 | .. self 49 | } 50 | } 51 | 52 | pub fn max_connections(self, max_connections: u32) -> Client { 53 | Client { 54 | max_connections: max_connections, 55 | .. self 56 | } 57 | } 58 | 59 | pub fn proxies(self, proxies: Vec) -> Client { 60 | Client { 61 | proxies: proxies, 62 | .. self 63 | } 64 | } 65 | } 66 | 67 | impl From for Response { 68 | fn from(res: hyper_client::response::Response) -> Response { 69 | let mut res = res; 70 | let mut body = String::new(); 71 | res.read_to_string(&mut body); 72 | let status_raw = res.status_raw(); 73 | let api_result = res.headers.get_raw("dropbox-api-result"); 74 | let api_result = api_result.map(|s| { 75 | String::from_utf8(s[0].clone()).unwrap() 76 | }); 77 | Response { 78 | status: status_raw.0, 79 | api_result: api_result, 80 | body: body, 81 | } 82 | } 83 | } 84 | 85 | impl DropboxClient for Client { 86 | fn access_token(&self) -> &str { 87 | self.token.as_ref() 88 | } 89 | 90 | fn request(&self, endpoint: Endpoint, url: &str, headers: &mut BTreeMap, body: Option) -> Result 91 | where T: rustc_serialize::Encodable + Clone 92 | { 93 | let endpoint = format!("{}", endpoint); 94 | let url = format!("https://{}.dropboxapi.com/2/{}", endpoint, url); 95 | let sbody = { 96 | if body.is_some() { 97 | let body = body.clone(); 98 | json::encode(&body.unwrap()).unwrap() 99 | } else { 100 | "".to_owned() 101 | } 102 | }; 103 | 104 | let mut hheaders = Headers::new(); 105 | 106 | for (key, value) in headers.iter() { 107 | hheaders.set_raw(key.to_owned(), vec![value.to_owned().into_bytes()]); 108 | } 109 | 110 | if !headers.contains_key("Content-Type") { 111 | hheaders.set( 112 | ContentType( 113 | Mime( 114 | TopLevel::Application, SubLevel::Json, vec![] 115 | ) 116 | ) 117 | ); 118 | } 119 | 120 | hheaders.set( 121 | Authorization( 122 | Bearer { 123 | token: self.access_token().to_owned(), 124 | } 125 | ) 126 | ); 127 | let hclient = hyper_client::Client::new(); 128 | let mut builder = hclient.post(&url).headers(hheaders); 129 | if body.is_some() { 130 | builder = builder.body(&sbody); 131 | } 132 | match builder.send() { 133 | Ok(mut res) => { 134 | match res.status { 135 | StatusCode::Ok => { 136 | Ok(From::from(res)) 137 | }, 138 | _ => { 139 | let mut _body = String::new(); 140 | res.read_to_string(&mut _body); 141 | println!("{:?}", _body); 142 | Err(ApiError::ClientError) 143 | } 144 | } 145 | 146 | }, 147 | Err(e) => { 148 | println!("{:?}", e); 149 | Err(ApiError::ClientError) 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/files.rs: -------------------------------------------------------------------------------- 1 | use super::{Result, Response, DropboxClient, ApiError}; 2 | use std::default::Default; 3 | use std::io::{self, Write, Read}; 4 | use std::fmt; 5 | use std::collections::BTreeMap; 6 | use rustc_serialize::json; 7 | 8 | use structs::{FolderList, Metadata, FileMetadata, NewFolder}; 9 | 10 | /// Instructs dropbox what to do when a conflict happens during upload 11 | #[derive(Debug, PartialEq, Clone)] 12 | pub enum WriteMode { 13 | Add, 14 | Overwrite, 15 | Update, 16 | } 17 | 18 | impl fmt::Display for WriteMode { 19 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 20 | match *self { 21 | WriteMode::Add => write!(f, "add"), 22 | WriteMode::Overwrite => write!(f, "overwrite"), 23 | WriteMode::Update => write!(f, "update"), 24 | } 25 | } 26 | } 27 | 28 | /// Optional arguments to the `upload` API call 29 | #[derive(Debug, PartialEq, Clone)] 30 | pub struct UploadOptions { 31 | pub mode: WriteMode, 32 | pub autorename: bool, 33 | pub client_modified: Option, 34 | pub mute: bool, 35 | } 36 | 37 | impl Default for UploadOptions { 38 | fn default() -> UploadOptions { 39 | UploadOptions { 40 | mode: WriteMode::Add, 41 | autorename: false, 42 | client_modified: None, 43 | mute: false, 44 | } 45 | } 46 | } 47 | 48 | #[derive(Debug, PartialEq, Clone)] 49 | pub enum ThumbnailFormat { 50 | Jpeg, 51 | Png, 52 | Gif, 53 | } 54 | 55 | #[derive(Debug, PartialEq, Clone)] 56 | pub enum ThumbnailSize { 57 | W16H16, 58 | W32H32, 59 | W64H64, 60 | Other(usize, usize), 61 | } 62 | 63 | #[derive(Debug, PartialEq, Clone)] 64 | pub struct ThumbnailOptions { 65 | format: ThumbnailFormat, 66 | size: ThumbnailSize, 67 | } 68 | 69 | impl Default for ThumbnailOptions { 70 | fn default() -> ThumbnailOptions { 71 | ThumbnailOptions { 72 | format: ThumbnailFormat::Jpeg, 73 | size: ThumbnailSize::W64H64, 74 | } 75 | } 76 | } 77 | 78 | #[derive(Debug, PartialEq, Clone)] 79 | pub struct GetCursorOptions { 80 | recursive: bool, 81 | include_media_info: bool, 82 | include_deleted: bool, 83 | } 84 | 85 | impl Default for GetCursorOptions { 86 | fn default() -> GetCursorOptions { 87 | GetCursorOptions { 88 | recursive: false, 89 | include_media_info: false, 90 | include_deleted: false, 91 | } 92 | } 93 | } 94 | 95 | #[derive(Debug, PartialEq, Clone)] 96 | pub struct FolderListLongpoll { 97 | changes: bool, 98 | backoff: Option, 99 | } 100 | 101 | #[derive(Debug, PartialEq, Clone)] 102 | pub struct ListRevisions { 103 | is_deleted: bool, 104 | entries: Vec, 105 | } 106 | 107 | #[derive(Debug, PartialEq, Clone)] 108 | pub enum SearchMode { 109 | Filename, 110 | FilenameAndContent, 111 | DeletedFilename, 112 | } 113 | 114 | #[derive(Debug, PartialEq, Clone)] 115 | pub struct SearchOptions { 116 | start: usize, 117 | max_results: usize, 118 | mode: SearchMode, 119 | } 120 | 121 | impl Default for SearchOptions { 122 | fn default() -> SearchOptions { 123 | SearchOptions { 124 | start: 0, 125 | max_results: 100, 126 | mode: SearchMode::Filename, 127 | } 128 | } 129 | } 130 | 131 | #[derive(Debug, PartialEq, Clone)] 132 | pub enum SearchMatchType { 133 | Filename(String), 134 | Content(String), 135 | Both(String), 136 | } 137 | 138 | #[derive(Debug, PartialEq, Clone)] 139 | pub struct SearchMatch { 140 | match_type: SearchMatchType, 141 | metadata: Metadata, 142 | } 143 | 144 | #[derive(Debug, PartialEq, Clone)] 145 | pub struct Search { 146 | matches: Vec, 147 | more: bool, 148 | start: usize, 149 | } 150 | 151 | #[derive(Debug, PartialEq, Clone)] 152 | pub struct CommitInfo { 153 | path: String, 154 | mode: WriteMode, 155 | autorename: bool, 156 | client_modified: String, 157 | mute: bool, 158 | } 159 | 160 | #[derive(Debug, PartialEq, Clone)] 161 | pub struct UploadSessionCursor { 162 | session_id: String, 163 | offset: usize, 164 | } 165 | 166 | // Functions 167 | 168 | /// Copy a file 169 | /// 170 | /// # Example 171 | /// 172 | /// ```ignore 173 | /// use std::env; 174 | /// use dbox::client::Client; 175 | /// use dbox::files; 176 | /// 177 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 178 | /// let metadata = try!(files::copy_(&client, "/Path/to/existing/file", "/Path/to/new/file")); 179 | /// ``` 180 | pub fn copy_(client: &T, from: &str, to: &str) -> Result 181 | where T: DropboxClient 182 | { 183 | let mut map = BTreeMap::new(); 184 | map.insert("from_path".to_string(), json::Json::String(from.to_string())); 185 | map.insert("to_path".to_string(), json::Json::String(to.to_string())); 186 | let mut headers = BTreeMap::new(); 187 | let resp = try!(client.api("files/copy", &mut headers, Some(&map))); 188 | json::decode(&resp.body).map_err(|e| ApiError::from(e)) 189 | } 190 | 191 | /// Create a folder 192 | /// 193 | /// # Example 194 | /// 195 | /// ```ignore 196 | /// use std::env; 197 | /// use dbox::client::Client; 198 | /// use dbox::files; 199 | /// 200 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 201 | /// let metadata = try!(files::create_folder(&client, "/Path/to/new/folder")); 202 | /// ``` 203 | pub fn create_folder(client: &T, path: &str) -> Result 204 | where T: DropboxClient 205 | { 206 | let mut map = BTreeMap::new(); 207 | map.insert("path".to_string(), json::Json::String(path.to_string())); 208 | let mut headers = BTreeMap::new(); 209 | let resp = try!(client.api("files/create_folder", &mut headers, Some(map))); 210 | json::decode(&resp.body).map_err(|e| ApiError::from(e)) 211 | } 212 | 213 | /// Delete a file or folder from the user's dropbox acconut 214 | /// 215 | /// # Example 216 | /// 217 | /// ```ignore 218 | /// use std::env; 219 | /// use dbox::client::Client; 220 | /// use dbox::files; 221 | /// 222 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 223 | /// let deleted = files::delete(&client, "/path/to/file/or/folder"); 224 | /// ``` 225 | /// TODO error handling 226 | pub fn delete(client: &T, path: &str) -> Result { 227 | let mut map = BTreeMap::new(); 228 | map.insert("path".to_string(), json::Json::String(path.to_string())); 229 | let mut headers = BTreeMap::new(); 230 | let resp = try!(client.api("files/delete", &mut headers, Some(map))); 231 | json::decode(&resp.body).map_err(|e| ApiError::from(e)) 232 | } 233 | 234 | /// Download a file 235 | /// 236 | /// # Example 237 | /// 238 | /// ```ignore 239 | /// use std::env; 240 | /// use dbox::client::Client; 241 | /// use dbox::files; 242 | /// 243 | /// let token = env::var("DROPBOX_TOKEN"); 244 | /// let client = Client::new(token); 245 | /// let (metadata, response) = try!(files::download(&client, "/Path/to/file")); 246 | /// ``` 247 | pub fn download(client: &T, path: &str) -> Result<(FileMetadata, Response)> { 248 | let mut map = BTreeMap::new(); 249 | map.insert("path".to_string(), json::Json::String(path.to_string())); 250 | let mut headers = BTreeMap::new(); 251 | headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap()); 252 | headers.insert("Content-Type".to_string(), "".to_string()); 253 | let resp = try!(client.content("files/download", &mut headers, None::<&str>)); 254 | let metadata: FileMetadata = match resp.api_result { 255 | Some(ref data) => { 256 | try!(json::decode(data)) 257 | }, 258 | None => return Err(ApiError::ClientError) 259 | }; 260 | Ok(( 261 | metadata, 262 | resp, 263 | )) 264 | } 265 | 266 | /// TODO implement 267 | pub fn download_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)> 268 | where T: DropboxClient 269 | { 270 | Ok(( 271 | Default::default(), 272 | Response { 273 | status: 200, 274 | api_result: None, 275 | body: "".to_string(), 276 | }, 277 | )) 278 | } 279 | 280 | pub fn download_to(client: &T, path: &str, writer: U) -> Result<(Metadata, Response)> 281 | where T: DropboxClient, 282 | U: Write 283 | { 284 | Ok(( 285 | Default::default(), 286 | Response { 287 | status: 200, 288 | api_result: None, 289 | body: "".to_string(), 290 | } 291 | )) 292 | } 293 | 294 | /// Get metadata for a file 295 | /// 296 | /// # Example 297 | /// 298 | /// ```ignore 299 | /// use std::env; 300 | /// use dbox::client::Client; 301 | /// use dbox::files; 302 | /// 303 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 304 | /// let metadata = try!(files::get_metadata(&client, "/path/to/file", false)); 305 | /// ``` 306 | /// 307 | /// TODO error handling 308 | pub fn get_metadata(client: &T, path: &str, include_media_info: bool) -> Result 309 | where T: DropboxClient 310 | { 311 | let mut map = BTreeMap::new(); 312 | map.insert("path", json::Json::String(path.to_string())); 313 | map.insert("include_media_info", json::Json::Boolean(include_media_info)); 314 | let mut headers = BTreeMap::new(); 315 | let resp = try!(client.api("files/get_metadata", &mut headers, Some(map))); 316 | json::decode(&resp.body).map_err(ApiError::from) 317 | } 318 | 319 | /// TODO implement 320 | pub fn get_preview(client: &T, path: &str) -> Result<(Metadata, Response)> 321 | where T: DropboxClient 322 | { 323 | Ok(( 324 | Default::default(), 325 | Response { 326 | status: 200, 327 | api_result: None, 328 | body: "".to_string(), 329 | }, 330 | )) 331 | } 332 | 333 | /// TODO implement 334 | pub fn get_preview_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)> 335 | where T: DropboxClient 336 | { 337 | Ok(( 338 | Default::default(), 339 | Response { 340 | status: 200, 341 | api_result: None, 342 | body: "".to_string(), 343 | }, 344 | )) 345 | } 346 | 347 | pub fn get_thumbnail(client: &T, path: &str) -> Result<(Metadata, Response)> 348 | where T: DropboxClient 349 | { 350 | get_thumbnail_with_options(client, path, Default::default()) 351 | } 352 | 353 | /// TODO implement 354 | pub fn get_thumbnail_with_options(client: &T, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)> 355 | where T: DropboxClient 356 | { 357 | Ok(( 358 | Default::default(), 359 | Response { 360 | status: 200, 361 | api_result: None, 362 | body: "".to_string(), 363 | }, 364 | )) 365 | } 366 | 367 | pub fn get_thumbnail_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)> 368 | where T: DropboxClient 369 | { 370 | get_thumbnail_to_file_with_options(client, dest_path, path, Default::default()) 371 | } 372 | 373 | /// TODO implement 374 | pub fn get_thumbnail_to_file_with_options(client: &T, dest_path: &str, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)> 375 | where T: DropboxClient 376 | { 377 | Ok(( 378 | Default::default(), 379 | Response { 380 | status: 200, 381 | api_result: None, 382 | body: "".to_string(), 383 | }, 384 | )) 385 | } 386 | 387 | /// List the entries in a user's dropbox folder 388 | /// 389 | /// # Example 390 | /// 391 | /// ```ignore 392 | /// use std::env; 393 | /// use dbox::client::Client; 394 | /// use dbox::files; 395 | /// 396 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 397 | /// let folderlist = files::list_folder(&client, "/path/to/folder"); 398 | /// ``` 399 | /// TODO error handling 400 | pub fn list_folder(client: &T, path: &str) -> Result { 401 | let mut map = BTreeMap::new(); 402 | map.insert("path".to_string(), json::Json::String(path.to_string())); 403 | map.insert("recursive".to_string(), json::Json::Boolean(false)); 404 | map.insert("include_media_info".to_string(), json::Json::Boolean(false)); 405 | map.insert("include_deleted".to_string(), json::Json::Boolean(false)); 406 | let mut headers = BTreeMap::new(); 407 | let resp = try!(client.api("files/list_folder", &mut headers, Some(&map))); 408 | json::decode(&resp.body).map_err(ApiError::from) 409 | } 410 | 411 | /// TODO implement 412 | pub fn list_folder_continue(client: &T, cursor: &str) -> Result 413 | where T: DropboxClient 414 | { 415 | Ok(Default::default()) 416 | } 417 | 418 | 419 | pub fn list_folder_get_latest_cursor(client: &T, path: &str) -> Result 420 | where T: DropboxClient 421 | { 422 | list_folder_get_latest_cursor_with_options(client, path, Default::default()) 423 | } 424 | 425 | /// TODO implement 426 | pub fn list_folder_get_latest_cursor_with_options(client: &T, path: &str, options: GetCursorOptions) -> Result 427 | where T: DropboxClient 428 | { 429 | Ok("".to_string()) 430 | } 431 | 432 | /// TODO implement 433 | pub fn list_folder_longpoll(client: &T, cursor: &str, timeout: usize) -> Result 434 | where T: DropboxClient 435 | { 436 | Ok(FolderListLongpoll { 437 | changes: false, 438 | backoff: None, 439 | }) 440 | } 441 | 442 | /// TODO implement 443 | pub fn list_revisions(client: &T, path: &str, limit: usize) -> Result 444 | where T: DropboxClient 445 | { 446 | Ok(ListRevisions { 447 | is_deleted: false, 448 | entries: vec![], 449 | }) 450 | } 451 | 452 | 453 | /// Move a file in a user's dropbox 454 | /// 455 | /// # Example 456 | /// 457 | /// ```ignore 458 | /// use std::env; 459 | /// use dbox::client::Client; 460 | /// use dbox::files; 461 | /// 462 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 463 | /// let metadata = try!(files::move(&client, "/path/to/existing/file", "/path/to/new/location/for/file")); 464 | /// ``` 465 | /// 466 | /// TODO error handling 467 | pub fn move_(client: &T, from: &str, to: &str) -> Result 468 | where T: DropboxClient 469 | { 470 | let mut map = BTreeMap::new(); 471 | map.insert("from_path", json::Json::String(from.to_string())); 472 | map.insert("to_path", json::Json::String(to.to_string())); 473 | let mut headers = BTreeMap::new(); 474 | let resp = try!(client.api("files/move", &mut headers, Some(map))); 475 | json::decode(&resp.body).map_err(ApiError::from) 476 | } 477 | 478 | /// TODO implement 479 | pub fn permanently_delete(client: &T, path: &str) -> Result<()> 480 | where T: DropboxClient 481 | { 482 | Ok(()) 483 | } 484 | 485 | /// TODO implement 486 | pub fn restore(client: &T, path: &str, rev: &str) -> Result 487 | where T: DropboxClient 488 | { 489 | Ok(Default::default()) 490 | } 491 | 492 | pub fn search(client: &T, path: &str, query: &str) -> Result 493 | where T: DropboxClient 494 | { 495 | search_with_options(client, path, query, Default::default()) 496 | } 497 | 498 | /// TODO implement 499 | pub fn search_with_options(client: &T, path: &str, query: &str, options: SearchOptions) -> Result 500 | where T: DropboxClient 501 | { 502 | Ok(Search { 503 | matches: vec![], 504 | more: false, 505 | start: 0, 506 | }) 507 | } 508 | 509 | /// Upload a file to the user's dropbox acconut 510 | /// 511 | /// # Example 512 | /// 513 | /// ```ignore 514 | /// use std::env; 515 | /// use dbox::client::Client; 516 | /// use dbox::files; 517 | /// 518 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 519 | /// let metadata = try!(files::upload(&client, "file contents", "/path/to/file")); 520 | /// ``` 521 | /// 522 | /// TODO error handling 523 | pub fn upload(client: &T, contents: &str, path: &str) -> Result 524 | where T: DropboxClient 525 | { 526 | upload_with_options(client, contents, path, Default::default()) 527 | } 528 | 529 | /// Upload a file to the user's dropbox acconut 530 | /// 531 | /// # Example 532 | /// 533 | /// ```ignore 534 | /// use std::env; 535 | /// use dbox::client::Client; 536 | /// use dbox::files; 537 | /// 538 | /// let client = Client::new(env::var("DROPBOX_TOKEN")); 539 | /// let upload_options = UploadOptions { mode: WriteMode::Overwrite, autorename: true, mute: false }; 540 | /// let metadata = try!(files::upload_with_options(&client, "file contents", "/path/to/file", upload_options)); 541 | /// ``` 542 | /// 543 | /// TODO error handling 544 | pub fn upload_with_options(client: &T, contents: &str, path: &str, options: UploadOptions) -> Result 545 | where T: DropboxClient 546 | { 547 | let mut map = BTreeMap::new(); 548 | map.insert("path", json::Json::String(path.to_string())); 549 | map.insert("mode", json::Json::String(format!("{}", options.mode))); 550 | map.insert("autorename", json::Json::Boolean(options.autorename)); 551 | map.insert("mute", json::Json::Boolean(options.mute)); 552 | let mut headers = BTreeMap::new(); 553 | headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap()); 554 | headers.insert("Content-Type".to_string(), "application/octet-stream".to_string()); 555 | let resp = try!(client.content("files/upload", &mut headers, Some(contents.to_owned()))); 556 | json::decode(&resp.body).map_err(ApiError::from) 557 | } 558 | 559 | /// TODO implement 560 | pub fn upload_session_append(client: &T, f: U, session_id: &str, offset: usize) -> Result<()> 561 | where T: DropboxClient, U: io::Read 562 | { 563 | Ok(()) 564 | } 565 | 566 | /// TODO implement 567 | pub fn upload_session_finish(client: &T, f: U, cursor: &UploadSessionCursor, commit: &CommitInfo) -> Result 568 | where T: DropboxClient, 569 | U: io::Read 570 | { 571 | Ok(Default::default()) 572 | } 573 | 574 | /// TODO implement 575 | pub fn upload_session_start(client: &T, f: U) -> Result 576 | where T: DropboxClient, 577 | U: io::Read 578 | { 579 | Ok("".to_string()) 580 | } 581 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | #![allow(unused_imports)] 3 | #![allow(unused_must_use)] 4 | 5 | //! Dropbox SDK for Rust 6 | //! 7 | //! This crate implements a simple client for the [Dropbox API](https://dropbox.com/developers). 8 | //! It uses [hyper](https://hyperium.github.io) for HTTP, though that part is swappable if you would 9 | //! like to use a different HTTP implementation. 10 | //! 11 | //! If you want to use hyper, just `use dbox::client::Client`, as in the example below. If, 12 | //! however, you want to use something else, you will need to implement the `DropboxClient` trait 13 | //! for your data structure, build this crate with `--no-default-features`, and pass a reference to 14 | //! your client as the first parameter to the API functions. 15 | //! 16 | //! # Example 17 | //! 18 | //! ```ignore 19 | //! extern crate dbox; 20 | //! 21 | //! use std::env; 22 | //! use dbox::client::Client; 23 | //! use dbox::files; 24 | //! 25 | //! let access_token = env::var("DROPBOX_TOKEN"); 26 | //! let client = Client::new(access_token); 27 | //! let folder_list = files::copy_(&client, "/path/to/existing/file", "/path/to/new/file"); 28 | //! ``` 29 | //! 30 | 31 | #[cfg(feature = "hyper-client")] extern crate hyper; 32 | extern crate chrono; 33 | extern crate rustc_serialize; 34 | 35 | #[cfg(test)] extern crate rand; 36 | 37 | use std::convert::From; 38 | use std::fmt; 39 | use std::collections::BTreeMap; 40 | 41 | #[doc(hidden)] 42 | pub enum Endpoint { 43 | Api, 44 | Content, 45 | } 46 | 47 | impl fmt::Display for Endpoint { 48 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 49 | match *self { 50 | Endpoint::Api => write!(f, "api"), 51 | Endpoint::Content => write!(f, "content"), 52 | } 53 | } 54 | } 55 | 56 | pub trait DropboxClient { 57 | fn access_token(&self) -> &str; 58 | fn request(&self, endpoint: Endpoint, url: &str, headers: &mut BTreeMap, body: Option) -> Result 59 | where T: rustc_serialize::Encodable + Clone; 60 | 61 | fn api(&self, url: &str, headers: &mut BTreeMap, body: Option) -> Result 62 | where T: rustc_serialize::Encodable + Clone 63 | { 64 | self.request(Endpoint::Api, url, headers, body) 65 | } 66 | 67 | fn content(&self, url: &str, headers: &mut BTreeMap, body: Option) -> Result 68 | where T: rustc_serialize::Encodable + Clone 69 | { 70 | self.request(Endpoint::Content, url, headers, body) 71 | } 72 | } 73 | 74 | /// Collection of possible errors 75 | #[derive(Debug, PartialEq, Clone)] 76 | pub enum ApiError { 77 | AddFolderMemberError, 78 | ClientError, 79 | CreateFolderError, 80 | CreateSharedLinkError, 81 | DeleteError, 82 | DownloadError, 83 | GetAccountError, 84 | GetAccountBatchError, 85 | GetMetadataError, 86 | GetSharedLinksError, 87 | ListFolderError, 88 | ListFolderContinueError, 89 | ListFolderLongpollError, 90 | ListFolderMembersContinueError, 91 | ListFoldersContinueError, 92 | ListRevisionsError, 93 | MountFolderError, 94 | PollError, 95 | PreviewError, 96 | RelinquishFolderMembershipError, 97 | RelocationError, 98 | RemoveFolderMemberError, 99 | RestoreError, 100 | RevokeSharedLinkError, 101 | SearchError, 102 | ShareFolderError, 103 | SharedFolderAccessError, 104 | ThumbnailError, 105 | TokenError, 106 | TransferFolderError, 107 | UnmountFolderError, 108 | UnshareFolderError, 109 | UpdateFolderMemberError, 110 | UpdateFolderPolicyError, 111 | UploadError, 112 | UploadSessionLookupError, 113 | UploadSessionFinishError, 114 | } 115 | 116 | impl From for ApiError { 117 | fn from(e: rustc_serialize::json::DecoderError) -> ApiError { 118 | ApiError::ClientError 119 | } 120 | } 121 | 122 | /// Simple abstraction of a HTTP response, to allow the HTTP client to be pluggable 123 | /// 124 | /// TODO: overhaul this 125 | #[derive(Debug, PartialEq, Clone)] 126 | pub struct Response { 127 | pub status: u16, 128 | pub api_result: Option, 129 | pub body: String, 130 | } 131 | 132 | pub type Result = ::std::result::Result; 133 | 134 | #[cfg(feature = "hyper-client")] 135 | /// Default implementation of the Dropbox Client 136 | pub mod client; 137 | /// Module for performing operations on files in a dropbox account 138 | pub mod files; 139 | /// Module that holds definitions for dropbox data structures 140 | pub mod structs; 141 | /// TODO 142 | pub mod sharing; 143 | /// TODO 144 | pub mod users; 145 | 146 | #[cfg(test)] 147 | mod tests { 148 | use super::client::Client; 149 | use super::files; 150 | use super::DropboxClient; 151 | use chrono::{DateTime, Local}; 152 | use rand; 153 | use std::str; 154 | use std::env; 155 | use std::default::Default; 156 | use rustc_serialize::json; 157 | 158 | const ACCESS_TOKEN: &'static str = "DROPBOX_TOKEN"; 159 | const MALFORMED_TOKEN: &'static str = "asdf"; 160 | 161 | fn random_ascii_letters(len: usize) -> String { 162 | let mut rng = rand::thread_rng(); 163 | let ascii_letters = (65..91).chain((97..123)).collect::>(); 164 | let random_bytes = rand::sample(&mut rng, ascii_letters.into_iter(), len); 165 | let random_string = str::from_utf8(&random_bytes).unwrap(); 166 | random_string.to_owned() 167 | } 168 | 169 | #[test] 170 | fn test_bad_auth() { 171 | if let Ok(_) = Client::new(MALFORMED_TOKEN) { 172 | panic!("Malformed token should not be accepted"); 173 | } 174 | 175 | let valid_looking_token = vec!["z"; 62].join(""); 176 | let client = Client::new(&valid_looking_token).unwrap(); 177 | if let Ok(_) = files::list_folder(&client, "") { 178 | panic!("Valid-looking but invalid token should not be accepted"); 179 | } 180 | } 181 | 182 | #[test] 183 | fn test_list_rpc() { 184 | let access_token = match env::var(ACCESS_TOKEN) { 185 | Ok(t) => t, 186 | Err(_) => panic!("No {} found", ACCESS_TOKEN), 187 | }; 188 | let client = Client::new(&access_token).unwrap(); 189 | assert!(files::create_folder(&client, "/testdir").is_ok()); 190 | assert!(files::list_folder(&client, "/testdir").is_ok()); 191 | assert!(files::delete(&client, "/testdir").is_ok()); 192 | } 193 | 194 | #[test] 195 | fn test_files() { 196 | let access_token = match env::var(ACCESS_TOKEN) { 197 | Ok(t) => t, 198 | Err(_) => panic!("No {} found", ACCESS_TOKEN), 199 | }; 200 | let random_filename = random_ascii_letters(15); 201 | let now: DateTime = Local::now(); 202 | let now = format!("{}", now.timestamp()); 203 | let random_dir = format!("/Test/{}", now); 204 | let random_path = format!("/Test/{}/{}", now, random_filename); 205 | let random_path_copy = format!("/Test/{}/{}copy", now, random_filename); 206 | let random_path_move = format!("/Test/{}/{}move", now, random_filename); 207 | let random_contents = random_ascii_letters(20); 208 | 209 | let client = Client::new(&access_token).unwrap(); 210 | 211 | assert!(files::upload(&client, &random_contents, &random_path).is_ok()); 212 | assert!(files::get_metadata(&client, &random_path, false).is_ok()); 213 | 214 | assert!(files::copy_(&client, &random_path, &random_path_copy).is_ok()); 215 | assert!(files::move_(&client, &random_path_copy, &random_path_move).is_ok()); 216 | 217 | let (metadata, resp) = files::download(&client, &random_path).unwrap(); 218 | let body: String = json::decode(&resp.body).unwrap(); 219 | assert_eq!(&body, &random_contents); 220 | 221 | assert!(files::delete(&client, &random_path_move).is_ok()); 222 | assert!(files::delete(&client, &random_path).is_ok()); 223 | assert!(files::delete(&client, &random_dir).is_ok()); 224 | } 225 | 226 | } 227 | -------------------------------------------------------------------------------- /src/sharing.rs: -------------------------------------------------------------------------------- 1 | use super::{Result, ApiError, Response, DropboxClient}; 2 | use std::default::Default; 3 | 4 | use structs::{FolderList, Metadata, SharingInfo, Tag}; 5 | 6 | #[derive(Debug, PartialEq, Clone)] 7 | pub enum JobError { 8 | AccessError(String), 9 | MemberError(String), 10 | Other(String), 11 | } 12 | 13 | #[derive(Debug, PartialEq, Clone)] 14 | pub enum SharePathError { 15 | AlreadyShared, 16 | ContainsSharedFolder, 17 | InsideAppFolder, 18 | InsideSharedFolder, 19 | InvalidPath, 20 | IsAppFolder, 21 | IsFile, 22 | Other(String), 23 | } 24 | 25 | #[derive(Debug, PartialEq, Clone)] 26 | pub enum ShareFolderError { 27 | EmailUnverified, 28 | BadPath(SharePathError), 29 | TeamPolicyDisallowsMemberPolicy, 30 | } 31 | 32 | #[derive(Debug, PartialEq, Clone)] 33 | pub struct AddFolderMemberOptions { 34 | quiet: bool, 35 | custom_message: Option, 36 | } 37 | 38 | impl Default for AddFolderMemberOptions { 39 | fn default() -> AddFolderMemberOptions { 40 | AddFolderMemberOptions { 41 | quiet: false, 42 | custom_message: None, 43 | } 44 | } 45 | } 46 | 47 | #[derive(Debug, PartialEq, Clone)] 48 | pub enum JobStatus { 49 | Complete, 50 | Failed(JobError), 51 | } 52 | 53 | #[derive(Debug, PartialEq, Clone)] 54 | pub enum ShareFolderJobStatus { 55 | Complete(Metadata), 56 | Failed(ShareFolderError), 57 | } 58 | 59 | #[derive(Debug, PartialEq, Clone)] 60 | pub struct CreateSharedLinkOptions { 61 | short_url: bool, 62 | pending_upload: Option, 63 | } 64 | 65 | impl Default for CreateSharedLinkOptions { 66 | fn default() -> CreateSharedLinkOptions { 67 | CreateSharedLinkOptions { 68 | short_url: false, 69 | pending_upload: None 70 | } 71 | } 72 | } 73 | 74 | #[derive(Debug, PartialEq, Clone)] 75 | pub enum PendingUploadMode { 76 | File, 77 | Folder, 78 | } 79 | 80 | #[derive(Debug, PartialEq, Clone)] 81 | pub struct SharedFolderMembers { 82 | users: Vec, 83 | groups: Vec, 84 | invitees: Vec, 85 | cursor: String, 86 | } 87 | 88 | #[derive(Debug, PartialEq, Clone)] 89 | pub struct UserMembershipInfo { 90 | access_type: AccessLevel, 91 | user: UserInfo, 92 | } 93 | 94 | #[derive(Debug, PartialEq, Clone)] 95 | pub struct GroupMembershipInfo { 96 | access_type: AccessLevel, 97 | group: GroupInfo, 98 | } 99 | 100 | #[derive(Debug, PartialEq, Clone)] 101 | pub struct InviteeMembershipInfo { 102 | access_type: AccessLevel, 103 | invitee: InviteeInfo, 104 | } 105 | 106 | #[derive(Debug, PartialEq, Clone)] 107 | pub enum AccessLevel { 108 | Owner, 109 | Editor, 110 | Viewer, 111 | Other(String), 112 | } 113 | 114 | #[derive(Debug, PartialEq, Clone)] 115 | pub struct UserInfo { 116 | account_id: String, 117 | same_team: bool, 118 | team_member_id: String, 119 | } 120 | 121 | #[derive(Debug, PartialEq, Clone)] 122 | pub struct GroupInfo { 123 | group_name: String, 124 | group_id: String, 125 | member_count: usize, 126 | same_team: bool, 127 | group_external_id: String, 128 | } 129 | 130 | #[derive(Debug, PartialEq, Clone)] 131 | pub enum InviteeInfo { 132 | Email(String), 133 | Other(String), 134 | } 135 | 136 | #[derive(Debug, PartialEq, Clone)] 137 | pub enum MemberSelector { 138 | DropboxID(String), 139 | Email(String), 140 | Other(String), 141 | } 142 | 143 | #[derive(Debug, PartialEq, Clone)] 144 | pub struct ShareFolderOptions { 145 | member_policy: MemberPolicy, 146 | acl_update_policy: AclUpdatePolicy, 147 | shared_link_policy: SharedLinkPolicy, 148 | force_async: bool, 149 | } 150 | 151 | impl Default for ShareFolderOptions { 152 | fn default() -> ShareFolderOptions { 153 | ShareFolderOptions { 154 | member_policy: MemberPolicy::Anyone, 155 | acl_update_policy: AclUpdatePolicy::Owner, 156 | shared_link_policy: SharedLinkPolicy::Anyone, 157 | force_async: false, 158 | } 159 | } 160 | } 161 | 162 | #[derive(Debug, PartialEq, Clone)] 163 | pub enum MemberPolicy { 164 | Team, 165 | Anyone, 166 | Other(String), 167 | } 168 | 169 | #[derive(Debug, PartialEq, Clone)] 170 | pub enum AclUpdatePolicy { 171 | Owner, 172 | Editors, 173 | Other(String), 174 | } 175 | 176 | #[derive(Debug, PartialEq, Clone)] 177 | pub enum SharedLinkPolicy { 178 | Anyone, 179 | Members, 180 | Other(String), 181 | } 182 | 183 | #[derive(Debug, PartialEq, Clone)] 184 | pub enum ShareFolderLaunch { 185 | Complete(Metadata), 186 | } 187 | 188 | #[derive(Debug, PartialEq, Clone)] 189 | pub struct UpdateFolderPolicyOptions { 190 | member_policy: Option, 191 | acl_update_policy: Option, 192 | shared_link_policy: Option, 193 | } 194 | 195 | impl Default for UpdateFolderPolicyOptions { 196 | fn default() -> UpdateFolderPolicyOptions { 197 | UpdateFolderPolicyOptions { 198 | member_policy: None, 199 | acl_update_policy: None, 200 | shared_link_policy: None, 201 | } 202 | } 203 | } 204 | 205 | // Functions 206 | pub fn add_folder_member(client: &T, shared_folder_id: &str, members: &[U]) -> Result<()> 207 | where T: DropboxClient, 208 | U: AsRef 209 | { 210 | add_folder_member_with_options(client, shared_folder_id, members, Default::default()) 211 | } 212 | 213 | pub fn add_folder_member_with_options(client: &T, shared_folder_id: &str, members: &[U], options: AddFolderMemberOptions) -> Result<()> 214 | where T: DropboxClient, 215 | U: AsRef 216 | { 217 | Ok(()) 218 | } 219 | 220 | pub fn check_job_status(client: &T, async_job_id: &str) -> Result 221 | where T: DropboxClient 222 | { 223 | Ok(JobStatus::Complete) 224 | } 225 | 226 | pub fn check_share_job_status(client: &T, async_job_id: &str) -> Result 227 | where T: DropboxClient 228 | { 229 | Ok(ShareFolderJobStatus::Complete(Default::default())) 230 | } 231 | 232 | pub fn create_shared_link(client: &T, path: &str) -> Result 233 | where T: DropboxClient 234 | { 235 | create_shared_link_with_options(client, path, Default::default()) 236 | } 237 | 238 | pub fn create_shared_link_with_options(client: &T, path: &str, options: CreateSharedLinkOptions) -> Result 239 | where T: DropboxClient 240 | { 241 | Ok(Default::default()) 242 | } 243 | 244 | pub fn get_folder_metadata(client: &T, shared_folder_id: &str) -> Result 245 | where T: DropboxClient 246 | { 247 | Ok(Default::default()) 248 | } 249 | 250 | pub fn get_shared_links(client: &T, path: Option<&str>) -> Result> 251 | where T: DropboxClient 252 | { 253 | Ok(vec![]) 254 | } 255 | 256 | pub fn list_folder_members(client: &T, shared_folder_id: &str) -> Result 257 | where T: DropboxClient 258 | { 259 | Ok(SharedFolderMembers { 260 | users: vec![], 261 | groups: vec![], 262 | invitees: vec![], 263 | cursor: "".to_string(), 264 | }) 265 | } 266 | 267 | pub fn list_folder_members_continue(client: &T, cursor: &str) -> Result 268 | where T: DropboxClient 269 | { 270 | Ok(SharedFolderMembers { 271 | users: vec![], 272 | groups: vec![], 273 | invitees: vec![], 274 | cursor: "".to_string(), 275 | }) 276 | } 277 | 278 | pub fn list_folders(client: &T) -> Result 279 | where T: DropboxClient 280 | { 281 | Ok(Default::default()) 282 | } 283 | 284 | pub fn list_folders_continue(client: &T, cursor: &str) -> Result 285 | where T: DropboxClient 286 | { 287 | Ok(Default::default()) 288 | } 289 | 290 | pub fn mount_folder(client: &T, shared_folder_id: &str) -> Result 291 | where T: DropboxClient 292 | { 293 | Ok(Default::default()) 294 | } 295 | 296 | pub fn relinquish_folder_membership(client: &T, shared_folder_id: &str) -> Result<()> 297 | where T: DropboxClient 298 | { 299 | Ok(()) 300 | } 301 | 302 | pub fn remove_folder_member(client: &T, 303 | shared_folder_id: &str, 304 | member: MemberSelector, 305 | leave_a_copy: bool) -> Result<()> 306 | where T: DropboxClient 307 | { 308 | Ok(()) 309 | } 310 | 311 | pub fn revoke_shared_link(client: &T, url: &str) -> Result<()> 312 | where T: DropboxClient 313 | { 314 | Ok(()) 315 | } 316 | 317 | pub fn share_folder(client: &T, path: &str) -> Result 318 | where T: DropboxClient 319 | { 320 | share_folder_with_options(client, path, Default::default()) 321 | } 322 | 323 | pub fn share_folder_with_options(client: &T, path: &str, options: ShareFolderOptions) -> Result 324 | where T: DropboxClient 325 | { 326 | Ok(ShareFolderLaunch::Complete(Default::default())) 327 | } 328 | 329 | pub fn transfer_folder(client: &T, shared_folder_id: &str, to_dropbox_id: &str) -> Result<()> 330 | where T: DropboxClient 331 | { 332 | Ok(()) 333 | } 334 | 335 | pub fn unmount_folder(client: &T, shared_folder_id: &str) -> Result<()> 336 | where T: DropboxClient 337 | { 338 | Ok(()) 339 | } 340 | 341 | pub fn unshare_folder(client: &T, shared_folder_id: &str, leave_a_copy: bool) -> Result<()> 342 | where T: DropboxClient 343 | { 344 | Ok(()) 345 | } 346 | 347 | pub fn update_folder_member(client: &T, 348 | shared_folder_id: &str, 349 | member: MemberSelector, 350 | access_level: AccessLevel) -> Result<()> 351 | where T: DropboxClient 352 | { 353 | Ok(()) 354 | } 355 | 356 | pub fn update_folder_policy(client: &T, shared_folder_id: &str) -> Result 357 | where T: DropboxClient 358 | { 359 | update_folder_policy_with_options(client, shared_folder_id, Default::default()) 360 | } 361 | 362 | pub fn update_folder_policy_with_options(client: &T, shared_folder_id: &str, options: UpdateFolderPolicyOptions) -> Result 363 | where T: DropboxClient 364 | { 365 | Ok(Default::default()) 366 | } 367 | -------------------------------------------------------------------------------- /src/structs.rs: -------------------------------------------------------------------------------- 1 | use std::default::Default; 2 | use rustc_serialize::{Encoder, Encodable, Decoder, Decodable}; 3 | 4 | #[derive(Debug, PartialEq, Clone)] 5 | pub enum Tag { 6 | File, 7 | Folder, 8 | } 9 | 10 | impl Encodable for Tag { 11 | fn encode(&self, encoder: &mut S) -> Result<(), S::Error> { 12 | encoder.emit_enum("Tag", |encoder| { 13 | match *self { 14 | Tag::File => encoder.emit_enum_variant("File", 0, 4, |encoder| "file".encode(encoder)), 15 | Tag::Folder => encoder.emit_enum_variant("Folder", 0, 6, |encoder| "folder".encode(encoder)), 16 | } 17 | }) 18 | } 19 | } 20 | 21 | impl Decodable for Tag { 22 | fn decode(decoder: &mut D) -> Result { 23 | decoder.read_enum("Tag", |decoder| { 24 | decoder.read_enum_variant(&["file", "folder"], |decoder, num| { 25 | Ok(match num { 26 | 0 => Tag::File, 27 | 1 => Tag::Folder, 28 | _ => unreachable!(), 29 | }) 30 | }) 31 | }) 32 | } 33 | } 34 | 35 | #[derive(Debug, PartialEq, Clone, RustcEncodable)] 36 | pub struct Metadata { 37 | tag: Tag, 38 | name: String, 39 | path_lower: String, 40 | id: String, 41 | size: Option, 42 | rev: Option, 43 | client_modified: Option, 44 | server_modified: Option, 45 | sharing_info: Option, 46 | } 47 | 48 | impl Decodable for Metadata { 49 | fn decode(decoder: &mut D) -> Result { 50 | decoder.read_struct("", 0, |decoder| { 51 | Ok(Metadata { 52 | tag: try!(decoder.read_struct_field(".tag", 0, |decoder| Decodable::decode(decoder))), 53 | name: try!(decoder.read_struct_field("name", 0, |decoder| Decodable::decode(decoder))), 54 | path_lower: try!(decoder.read_struct_field("path_lower", 0, |decoder| Decodable::decode(decoder))), 55 | id: try!(decoder.read_struct_field("id", 0, |decoder| Decodable::decode(decoder))), 56 | client_modified: try!(decoder.read_struct_field("client_modified", 0, |decoder| Decodable::decode(decoder))), 57 | server_modified: try!(decoder.read_struct_field("server_modified", 0, |decoder| Decodable::decode(decoder))), 58 | rev: try!(decoder.read_struct_field("rev", 0, |decoder| Decodable::decode(decoder))), 59 | size: try!(decoder.read_struct_field("size", 0, |decoder| Decodable::decode(decoder))), 60 | sharing_info: try!(decoder.read_struct_field("sharing_info", 0, |decoder| Decodable::decode(decoder))), 61 | }) 62 | }) 63 | } 64 | } 65 | 66 | impl Default for Metadata { 67 | fn default() -> Metadata { 68 | Metadata { 69 | tag: Tag::File, 70 | name: "".to_string(), 71 | path_lower: "".to_string(), 72 | id: "".to_string(), 73 | size: Some(0), 74 | rev: Some("".to_string()), 75 | client_modified: Some("".to_string()), 76 | server_modified: Some("".to_string()), 77 | sharing_info: Some(SharingInfo { 78 | read_only: false, 79 | parent_shared_folder_id: "".to_string() 80 | }), 81 | } 82 | } 83 | } 84 | 85 | #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] 86 | pub struct FileMetadata { 87 | name: String, 88 | path_lower: String, 89 | id: String, 90 | client_modified: String, 91 | server_modified: String, 92 | rev: String, 93 | size: usize, 94 | sharing_info: Option, 95 | media_info: Option<()>, 96 | } 97 | 98 | impl Default for FileMetadata { 99 | fn default() -> FileMetadata { 100 | FileMetadata { 101 | name: "".to_string(), 102 | path_lower: "".to_string(), 103 | client_modified: "".to_string(), 104 | server_modified: "".to_string(), 105 | rev: "".to_string(), 106 | size: 0, 107 | id: "".to_string(), 108 | sharing_info: None, 109 | media_info: None, 110 | } 111 | } 112 | } 113 | 114 | /// Struct that is returned from the `list_folder` API call 115 | #[derive(RustcEncodable, RustcDecodable, Debug, PartialEq, Clone)] 116 | pub struct FolderList { 117 | entries: Vec, 118 | cursor: String, 119 | has_more: bool, 120 | } 121 | 122 | impl Default for FolderList { 123 | fn default() -> FolderList { 124 | FolderList { 125 | entries: vec![], 126 | cursor: "".to_string(), 127 | has_more: false, 128 | } 129 | } 130 | } 131 | 132 | #[derive(PartialEq, Debug, Clone, RustcEncodable, RustcDecodable)] 133 | pub struct NewFolder { 134 | name: String, 135 | path_lower: String, 136 | id: String, 137 | } 138 | 139 | #[derive(RustcEncodable, RustcDecodable, Debug, PartialEq, Clone)] 140 | pub struct SharingInfo { 141 | read_only: bool, 142 | parent_shared_folder_id: String, 143 | } 144 | -------------------------------------------------------------------------------- /src/users.rs: -------------------------------------------------------------------------------- 1 | use super::{Result, ApiError, Response, DropboxClient}; 2 | use std::default::Default; 3 | 4 | use structs::{FolderList, Metadata, SharingInfo, Tag}; 5 | 6 | #[derive(Debug, PartialEq, Clone)] 7 | pub struct BasicAccount { 8 | account_id: Option, 9 | name: Option, 10 | is_teammate: Option, 11 | } 12 | 13 | #[derive(Debug, PartialEq, Clone)] 14 | pub struct FullAccount { 15 | account_id: String, 16 | name: String, 17 | email: String, 18 | locale: String, 19 | referral_link: String, 20 | is_paired: bool, 21 | account_type: String, 22 | country: String, 23 | team: Option, 24 | } 25 | 26 | #[derive(Debug, PartialEq, Clone)] 27 | pub struct SpaceUsage { 28 | used: usize, 29 | allocation: usize, 30 | } 31 | 32 | // Functions 33 | 34 | pub fn get_account(client: &T, account_id: &str) -> Result 35 | where T: DropboxClient 36 | { 37 | Ok(BasicAccount { 38 | account_id: None, 39 | name: None, 40 | is_teammate: None, 41 | }) 42 | } 43 | 44 | pub fn get_account_batch(client: &T, account_ids: &[U]) -> Result> 45 | where T: DropboxClient, 46 | U: AsRef 47 | { 48 | if account_ids.len() > 300 { 49 | return Err(ApiError::GetAccountBatchError); 50 | } 51 | Ok(vec![]) 52 | } 53 | 54 | pub fn get_current_account(client: &T) -> Result 55 | where T: DropboxClient 56 | { 57 | Ok(FullAccount { 58 | account_id: "".to_string(), 59 | name: "".to_string(), 60 | email: "".to_string(), 61 | locale: "".to_string(), 62 | referral_link: "".to_string(), 63 | is_paired: false, 64 | account_type: "".to_string(), 65 | country: "".to_string(), 66 | team: None, 67 | }) 68 | } 69 | 70 | pub fn get_space_usage(client: &T) -> Result 71 | where T: DropboxClient 72 | { 73 | Ok(SpaceUsage { 74 | used: 0, 75 | allocation: 0, 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /tags: -------------------------------------------------------------------------------- 1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ 2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ 3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ 4 | !_TAG_PROGRAM_NAME Exuberant Ctags // 5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ 6 | !_TAG_PROGRAM_VERSION 5.9~svn20110310 // 7 | AccessLevel ./src/sharing.rs /^pub enum AccessLevel {$/;" g 8 | AclUpdatePolicy ./src/sharing.rs /^pub enum AclUpdatePolicy {$/;" g 9 | AddFolderMemberOptions ./src/sharing.rs /^pub struct AddFolderMemberOptions {$/;" s 10 | ApiError ./src/lib.rs /^pub enum ApiError {$/;" g 11 | BasicAccount ./src/users.rs /^pub struct BasicAccount {$/;" s 12 | Client ./src/client.rs /^impl Client {$/;" i 13 | Client ./src/client.rs /^pub struct Client {$/;" s 14 | CommitInfo ./src/files.rs /^pub struct CommitInfo {$/;" s 15 | CreateSharedLinkOptions ./src/sharing.rs /^pub struct CreateSharedLinkOptions {$/;" s 16 | Decodable for Metadata ./src/structs.rs /^impl Decodable for Metadata {$/;" i 17 | Decodable for Tag ./src/structs.rs /^impl Decodable for Tag {$/;" i 18 | Default for AddFolderMemberOptions ./src/sharing.rs /^impl Default for AddFolderMemberOptions {$/;" i 19 | Default for CreateSharedLinkOptions ./src/sharing.rs /^impl Default for CreateSharedLinkOptions {$/;" i 20 | Default for FileMetadata ./src/structs.rs /^impl Default for FileMetadata {$/;" i 21 | Default for FolderList ./src/structs.rs /^impl Default for FolderList {$/;" i 22 | Default for GetCursorOptions ./src/files.rs /^impl Default for GetCursorOptions {$/;" i 23 | Default for Metadata ./src/structs.rs /^impl Default for Metadata {$/;" i 24 | Default for SearchOptions ./src/files.rs /^impl Default for SearchOptions {$/;" i 25 | Default for ShareFolderOptions ./src/sharing.rs /^impl Default for ShareFolderOptions {$/;" i 26 | Default for ThumbnailOptions ./src/files.rs /^impl Default for ThumbnailOptions {$/;" i 27 | Default for UpdateFolderPolicyOptions ./src/sharing.rs /^impl Default for UpdateFolderPolicyOptions {$/;" i 28 | Default for UploadOptions ./src/files.rs /^impl Default for UploadOptions {$/;" i 29 | DropboxClient ./src/lib.rs /^pub trait DropboxClient {$/;" t 30 | DropboxClient for Client ./src/client.rs /^impl DropboxClient for Client {$/;" i 31 | Encodable for Tag ./src/structs.rs /^impl Encodable for Tag {$/;" i 32 | Endpoint ./src/lib.rs /^pub enum Endpoint {$/;" g 33 | FileMetadata ./src/structs.rs /^pub struct FileMetadata {$/;" s 34 | FolderList ./src/structs.rs /^pub struct FolderList {$/;" s 35 | FolderListLongpoll ./src/files.rs /^pub struct FolderListLongpoll {$/;" s 36 | From for ApiError ./src/lib.rs /^impl From for ApiError {$/;" i 37 | From for Response ./src/client.rs /^impl From for Response {$/;" i 38 | FullAccount ./src/users.rs /^pub struct FullAccount {$/;" s 39 | GetCursorOptions ./src/files.rs /^pub struct GetCursorOptions {$/;" s 40 | GroupInfo ./src/sharing.rs /^pub struct GroupInfo {$/;" s 41 | GroupMembershipInfo ./src/sharing.rs /^pub struct GroupMembershipInfo {$/;" s 42 | InviteeInfo ./src/sharing.rs /^pub enum InviteeInfo {$/;" g 43 | InviteeMembershipInfo ./src/sharing.rs /^pub struct InviteeMembershipInfo {$/;" s 44 | JobError ./src/sharing.rs /^pub enum JobError {$/;" g 45 | JobStatus ./src/sharing.rs /^pub enum JobStatus {$/;" g 46 | ListRevisions ./src/files.rs /^pub struct ListRevisions {$/;" s 47 | MemberPolicy ./src/sharing.rs /^pub enum MemberPolicy {$/;" g 48 | MemberSelector ./src/sharing.rs /^pub enum MemberSelector {$/;" g 49 | Metadata ./src/structs.rs /^pub struct Metadata {$/;" s 50 | NewFolder ./src/structs.rs /^pub struct NewFolder {$/;" s 51 | PendingUploadMode ./src/sharing.rs /^pub enum PendingUploadMode {$/;" g 52 | Response ./src/lib.rs /^pub struct Response {$/;" s 53 | Result ./src/lib.rs /^pub type Result = ::std::result::Result;$/;" T 54 | Search ./src/files.rs /^pub struct Search {$/;" s 55 | SearchMatch ./src/files.rs /^pub struct SearchMatch {$/;" s 56 | SearchMatchType ./src/files.rs /^pub enum SearchMatchType {$/;" g 57 | SearchMode ./src/files.rs /^pub enum SearchMode {$/;" g 58 | SearchOptions ./src/files.rs /^pub struct SearchOptions {$/;" s 59 | ShareFolderError ./src/sharing.rs /^pub enum ShareFolderError {$/;" g 60 | ShareFolderJobStatus ./src/sharing.rs /^pub enum ShareFolderJobStatus {$/;" g 61 | ShareFolderLaunch ./src/sharing.rs /^pub enum ShareFolderLaunch {$/;" g 62 | ShareFolderOptions ./src/sharing.rs /^pub struct ShareFolderOptions {$/;" s 63 | SharePathError ./src/sharing.rs /^pub enum SharePathError {$/;" g 64 | SharedFolderMembers ./src/sharing.rs /^pub struct SharedFolderMembers {$/;" s 65 | SharedLinkPolicy ./src/sharing.rs /^pub enum SharedLinkPolicy {$/;" g 66 | SharingInfo ./src/structs.rs /^pub struct SharingInfo {$/;" s 67 | SpaceUsage ./src/users.rs /^pub struct SpaceUsage {$/;" s 68 | Tag ./src/structs.rs /^pub enum Tag {$/;" g 69 | ThumbnailFormat ./src/files.rs /^pub enum ThumbnailFormat {$/;" g 70 | ThumbnailOptions ./src/files.rs /^pub struct ThumbnailOptions {$/;" s 71 | ThumbnailSize ./src/files.rs /^pub enum ThumbnailSize {$/;" g 72 | UpdateFolderPolicyOptions ./src/sharing.rs /^pub struct UpdateFolderPolicyOptions {$/;" s 73 | UploadOptions ./src/files.rs /^pub struct UploadOptions {$/;" s 74 | UploadSessionCursor ./src/files.rs /^pub struct UploadSessionCursor {$/;" s 75 | UserInfo ./src/sharing.rs /^pub struct UserInfo {$/;" s 76 | UserMembershipInfo ./src/sharing.rs /^pub struct UserMembershipInfo {$/;" s 77 | WriteMode ./src/files.rs /^pub enum WriteMode {$/;" g 78 | access_token ./src/client.rs /^ fn access_token(&self) -> &str {$/;" f 79 | access_token ./src/lib.rs /^ fn access_token(&self) -> &str;$/;" f 80 | add_folder_member ./src/sharing.rs /^pub fn add_folder_member(client: &T, shared_folder_id: &str, members: &[U]) -> Result<()>$/;" f 81 | add_folder_member_with_options ./src/sharing.rs /^pub fn add_folder_member_with_options(client: &T, shared_folder_id: &str, members: &[U], options: AddFolderMemberOptions) -> Result<()>$/;" f 82 | api ./src/lib.rs /^ fn api(&self, url: &str, headers: &mut BTreeMap, body: Option) -> Result$/;" f 83 | check_job_status ./src/sharing.rs /^pub fn check_job_status(client: &T, async_job_id: &str) -> Result$/;" f 84 | check_share_job_status ./src/sharing.rs /^pub fn check_share_job_status(client: &T, async_job_id: &str) -> Result$/;" f 85 | client ./src/lib.rs /^pub mod client;$/;" m 86 | content ./src/lib.rs /^ fn content(&self, url: &str, headers: &mut BTreeMap, body: Option) -> Result$/;" f 87 | copy_ ./src/files.rs /^pub fn copy_(client: &T, from: &str, to: &str) -> Result$/;" f 88 | create_folder ./src/files.rs /^pub fn create_folder(client: &T, path: &str) -> Result$/;" f 89 | create_shared_link ./src/sharing.rs /^pub fn create_shared_link(client: &T, path: &str) -> Result$/;" f 90 | create_shared_link_with_options ./src/sharing.rs /^pub fn create_shared_link_with_options(client: &T, path: &str, options: CreateSharedLinkOptions) -> Result$/;" f 91 | decode ./src/structs.rs /^ fn decode(decoder: &mut D) -> Result {$/;" f 92 | decode ./src/structs.rs /^ fn decode(decoder: &mut D) -> Result {$/;" f 93 | default ./src/files.rs /^ fn default() -> GetCursorOptions {$/;" f 94 | default ./src/files.rs /^ fn default() -> SearchOptions {$/;" f 95 | default ./src/files.rs /^ fn default() -> ThumbnailOptions {$/;" f 96 | default ./src/files.rs /^ fn default() -> UploadOptions {$/;" f 97 | default ./src/sharing.rs /^ fn default() -> AddFolderMemberOptions {$/;" f 98 | default ./src/sharing.rs /^ fn default() -> CreateSharedLinkOptions {$/;" f 99 | default ./src/sharing.rs /^ fn default() -> ShareFolderOptions {$/;" f 100 | default ./src/sharing.rs /^ fn default() -> UpdateFolderPolicyOptions {$/;" f 101 | default ./src/structs.rs /^ fn default() -> FileMetadata {$/;" f 102 | default ./src/structs.rs /^ fn default() -> FolderList {$/;" f 103 | default ./src/structs.rs /^ fn default() -> Metadata {$/;" f 104 | delete ./src/files.rs /^pub fn delete(client: &T, path: &str) -> Result {$/;" f 105 | download ./src/files.rs /^pub fn download(client: &T, path: &str) -> Result<(FileMetadata, Response)> {$/;" f 106 | download_to ./src/files.rs /^pub fn download_to(client: &T, path: &str, writer: U) -> Result<(Metadata, Response)>$/;" f 107 | download_to_file ./src/files.rs /^pub fn download_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>$/;" f 108 | encode ./src/structs.rs /^ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {$/;" f 109 | files ./src/lib.rs /^pub mod files;$/;" m 110 | fmt ./src/files.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f 111 | fmt ./src/lib.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f 112 | fmt::Display for Endpoint ./src/lib.rs /^impl fmt::Display for Endpoint {$/;" i 113 | fmt::Display for WriteMode ./src/files.rs /^impl fmt::Display for WriteMode {$/;" i 114 | from ./src/client.rs /^ fn from(res: hyper_client::response::Response) -> Response {$/;" f 115 | from ./src/lib.rs /^ fn from(e: rustc_serialize::json::DecoderError) -> ApiError {$/;" f 116 | get_account ./src/users.rs /^pub fn get_account(client: &T, account_id: &str) -> Result$/;" f 117 | get_account_batch ./src/users.rs /^pub fn get_account_batch(client: &T, account_ids: &[U]) -> Result>$/;" f 118 | get_current_account ./src/users.rs /^pub fn get_current_account(client: &T) -> Result$/;" f 119 | get_folder_metadata ./src/sharing.rs /^pub fn get_folder_metadata(client: &T, shared_folder_id: &str) -> Result$/;" f 120 | get_metadata ./src/files.rs /^pub fn get_metadata(client: &T, path: &str, include_media_info: bool) -> Result$/;" f 121 | get_preview ./src/files.rs /^pub fn get_preview(client: &T, path: &str) -> Result<(Metadata, Response)>$/;" f 122 | get_preview_to_file ./src/files.rs /^pub fn get_preview_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>$/;" f 123 | get_shared_links ./src/sharing.rs /^pub fn get_shared_links(client: &T, path: Option<&str>) -> Result>$/;" f 124 | get_space_usage ./src/users.rs /^pub fn get_space_usage(client: &T) -> Result$/;" f 125 | get_thumbnail ./src/files.rs /^pub fn get_thumbnail(client: &T, path: &str) -> Result<(Metadata, Response)>$/;" f 126 | get_thumbnail_to_file ./src/files.rs /^pub fn get_thumbnail_to_file(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>$/;" f 127 | get_thumbnail_to_file_with_options ./src/files.rs /^pub fn get_thumbnail_to_file_with_options(client: &T, dest_path: &str, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>$/;" f 128 | get_thumbnail_with_options ./src/files.rs /^pub fn get_thumbnail_with_options(client: &T, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>$/;" f 129 | list_folder ./src/files.rs /^pub fn list_folder(client: &T, path: &str) -> Result {$/;" f 130 | list_folder_continue ./src/files.rs /^pub fn list_folder_continue(client: &T, cursor: &str) -> Result$/;" f 131 | list_folder_get_latest_cursor ./src/files.rs /^pub fn list_folder_get_latest_cursor(client: &T, path: &str) -> Result$/;" f 132 | list_folder_get_latest_cursor_with_options ./src/files.rs /^pub fn list_folder_get_latest_cursor_with_options(client: &T, path: &str, options: GetCursorOptions) -> Result$/;" f 133 | list_folder_longpoll ./src/files.rs /^pub fn list_folder_longpoll(client: &T, cursor: &str, timeout: usize) -> Result$/;" f 134 | list_folder_members ./src/sharing.rs /^pub fn list_folder_members(client: &T, shared_folder_id: &str) -> Result$/;" f 135 | list_folder_members_continue ./src/sharing.rs /^pub fn list_folder_members_continue(client: &T, cursor: &str) -> Result$/;" f 136 | list_folders ./src/sharing.rs /^pub fn list_folders(client: &T) -> Result$/;" f 137 | list_folders_continue ./src/sharing.rs /^pub fn list_folders_continue(client: &T, cursor: &str) -> Result$/;" f 138 | list_revisions ./src/files.rs /^pub fn list_revisions(client: &T, path: &str, limit: usize) -> Result$/;" f 139 | max_connections ./src/client.rs /^ pub fn max_connections(self, max_connections: u32) -> Client {$/;" f 140 | max_retries ./src/client.rs /^ pub fn max_retries(self, max_retries: u32) -> Client {$/;" f 141 | mount_folder ./src/sharing.rs /^pub fn mount_folder(client: &T, shared_folder_id: &str) -> Result$/;" f 142 | move_ ./src/files.rs /^pub fn move_(client: &T, from: &str, to: &str) -> Result$/;" f 143 | new ./src/client.rs /^ pub fn new(token: &str) -> Result {$/;" f 144 | permanently_delete ./src/files.rs /^pub fn permanently_delete(client: &T, path: &str) -> Result<()>$/;" f 145 | proxies ./src/client.rs /^ pub fn proxies(self, proxies: Vec) -> Client {$/;" f 146 | random_ascii_letters ./src/lib.rs /^ fn random_ascii_letters(len: usize) -> String {$/;" f 147 | relinquish_folder_membership ./src/sharing.rs /^pub fn relinquish_folder_membership(client: &T, shared_folder_id: &str) -> Result<()>$/;" f 148 | remove_folder_member ./src/sharing.rs /^pub fn remove_folder_member(client: &T,$/;" f 149 | request ./src/client.rs /^ fn request(&self, endpoint: Endpoint, url: &str, headers: &mut BTreeMap, body: Option) -> Result$/;" f 150 | request ./src/lib.rs /^ fn request(&self, endpoint: Endpoint, url: &str, headers: &mut BTreeMap, body: Option) -> Result$/;" f 151 | restore ./src/files.rs /^pub fn restore(client: &T, path: &str, rev: &str) -> Result$/;" f 152 | revoke_shared_link ./src/sharing.rs /^pub fn revoke_shared_link(client: &T, url: &str) -> Result<()>$/;" f 153 | search ./src/files.rs /^pub fn search(client: &T, path: &str, query: &str) -> Result$/;" f 154 | search_with_options ./src/files.rs /^pub fn search_with_options(client: &T, path: &str, query: &str, options: SearchOptions) -> Result$/;" f 155 | share_folder ./src/sharing.rs /^pub fn share_folder(client: &T, path: &str) -> Result$/;" f 156 | share_folder_with_options ./src/sharing.rs /^pub fn share_folder_with_options(client: &T, path: &str, options: ShareFolderOptions) -> Result$/;" f 157 | sharing ./src/lib.rs /^pub mod sharing;$/;" m 158 | structs ./src/lib.rs /^pub mod structs;$/;" m 159 | test_bad_auth ./src/lib.rs /^ fn test_bad_auth() {$/;" f 160 | test_list_rpc ./src/lib.rs /^ fn test_list_rpc() {$/;" f 161 | test_upload_download ./src/lib.rs /^ fn test_upload_download() {$/;" f 162 | tests ./src/lib.rs /^mod tests {$/;" m 163 | transfer_folder ./src/sharing.rs /^pub fn transfer_folder(client: &T, shared_folder_id: &str, to_dropbox_id: &str) -> Result<()>$/;" f 164 | unmount_folder ./src/sharing.rs /^pub fn unmount_folder(client: &T, shared_folder_id: &str) -> Result<()>$/;" f 165 | unshare_folder ./src/sharing.rs /^pub fn unshare_folder(client: &T, shared_folder_id: &str, leave_a_copy: bool) -> Result<()>$/;" f 166 | update_folder_member ./src/sharing.rs /^pub fn update_folder_member(client: &T,$/;" f 167 | update_folder_policy ./src/sharing.rs /^pub fn update_folder_policy(client: &T, shared_folder_id: &str) -> Result$/;" f 168 | update_folder_policy_with_options ./src/sharing.rs /^pub fn update_folder_policy_with_options(client: &T, shared_folder_id: &str, options: UpdateFolderPolicyOptions) -> Result$/;" f 169 | upload ./src/files.rs /^pub fn upload(client: &T, contents: &str, path: &str) -> Result$/;" f 170 | upload_session_append ./src/files.rs /^pub fn upload_session_append(client: &T, f: U, session_id: &str, offset: usize) -> Result<()>$/;" f 171 | upload_session_finish ./src/files.rs /^pub fn upload_session_finish(client: &T, f: U, cursor: &UploadSessionCursor, commit: &CommitInfo) -> Result$/;" f 172 | upload_session_start ./src/files.rs /^pub fn upload_session_start(client: &T, f: U) -> Result$/;" f 173 | upload_with_options ./src/files.rs /^pub fn upload_with_options(client: &T, contents: &str, path: &str, options: UploadOptions) -> Result$/;" f 174 | user_agent ./src/client.rs /^ pub fn user_agent(self, user_agent: &str) -> Client {$/;" f 175 | users ./src/lib.rs /^pub mod users;$/;" m 176 | --------------------------------------------------------------------------------