├── .gitignore ├── .travis.yml ├── CHANGELOG.MD ├── CONTRIBUTOR ├── COPYING ├── Cargo.toml ├── LICENSE ├── README.md ├── appveyor.yml └── src ├── config.rs ├── dns ├── add_service.rs ├── delete_dns.rs ├── delete_service.rs ├── get_file.rs ├── get_long_names.rs ├── get_service_directory.rs ├── get_services.rs ├── mod.rs ├── register_dns.rs └── register_public_id.rs ├── errors.rs ├── helper.rs ├── launcher_config_handler.rs ├── lib.rs ├── macros.rs ├── nfs ├── create_dir.rs ├── create_file.rs ├── delete_dir.rs ├── delete_file.rs ├── directory_response.rs ├── file_response.rs ├── get_dir.rs ├── get_file.rs ├── mod.rs ├── modify_dir.rs ├── modify_file.rs ├── move_dir.rs └── move_file.rs └── test_utils.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Executables 2 | *.exe 3 | *.out 4 | 5 | # Libraires and Objects 6 | *.o 7 | *.a 8 | *.so 9 | *.lo 10 | *.lib 11 | *.dll 12 | *.rlib 13 | *.dylib 14 | 15 | # Generated by Cargo 16 | bin/ 17 | tags* 18 | *.lock 19 | build/ 20 | target/ 21 | build-tests/ 22 | 23 | # Generated by Editors 24 | ~* 25 | *.swp 26 | *.sublime-* 27 | 28 | # Manual 29 | .cargo/ 30 | 31 | # Misc 32 | packages/ 33 | .DS_Store 34 | *.bootstrap.cache 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - secure: KUncRI5Kdh5R0Hrc6htOIIEWXAtU3Y9Csu9Moi12rVTCJTGDOSJm3yQJWo54s61IS6Q83QBJJTx/TleAQxSFfZ4wT+9Lf2BTqoxTwrki0fVo6z+9xr0ntoVWsbAIDb+BChU7l7uMSRkgqxmixvjrUMPQJdpasI5RsLJ4/ZZvXs3A2Lup3jsvAAkU563NMydofIrh+veHEiOTnOBw++T1MnYAJagWLBczxLMPZ4XjfbE1RDqk6dJUw+2bD5XDGo0R4OC1pRHORKs8xccaM3zHnunO+PMHsHJg4G921x9nhCkAhbEJ8Vr1f4Ep/dNHOeXEJbACX0orp5i0Rm0f+WSiM17Y5W3LXajM+Sy12ZY/iArDhhygJPOMT7pfr+9JhxWTi6TPi7pQCfKi5BX7WHAEDDEdpywktVaC7jDNSgcLmzpdTk7jnyXwpkhLPA8lq7w9B9tM+YKJV3k3gjwyq96l7CzX/KUPZXLCBQSeRIRB9NcXz4msHSWZZgVlIK8oqCnmOcABe6iO+EkZW/fZoO31T6yrcTyCY8BAHBs+IulgJ7GTPeibuqRZ5OS1cm4s0ogwtRiACP8wqrmQYpy6v0S4FT6dqHE7h8epLx2DbAddWX0s/TaetDeUNRdkvHRbM+fIGYE+HsHpaw9YAhzuuRljZ/fSjpumPb4aLN3B0euIb+g= 4 | - Features=use-mock-routing 5 | os: 6 | - linux 7 | - osx 8 | language: rust 9 | rust: 10 | - stable 11 | - nightly 12 | matrix: 13 | allow_failures: 14 | - rust: nightly 15 | sudo: false 16 | branches: 17 | only: 18 | - master 19 | cache: 20 | cargo: true 21 | directories: 22 | - $HOME/libsodium 23 | - $HOME/elfutils 24 | install: 25 | - curl -sSLO https://github.com/maidsafe/QA/raw/master/Bash%20Scripts/Travis/install_libsodium.sh 26 | - . install_libsodium.sh 27 | script: 28 | - curl -sSL https://github.com/maidsafe/QA/raw/master/Bash%20Scripts/Travis/build_and_run_tests.sh | bash 29 | before_cache: 30 | - curl -sSLO https://github.com/maidsafe/QA/raw/master/Bash%20Scripts/Travis/install_elfutils.sh 31 | - . install_elfutils.sh 32 | after_success: 33 | - curl -sSL https://github.com/maidsafe/QA/raw/master/Bash%20Scripts/Travis/after_success.sh | bash 34 | -------------------------------------------------------------------------------- /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | # Safe ffi - Change Log 2 | 3 | #[0.6.2] 4 | - Default logging function called so that logging can be configured via log.toml file 5 | - Dependency update 6 | 7 | #[0.6.1] 8 | - safe_core's dependency on mpid_messaging has been removed from it's Cargo.toml and patch version increased. Consequently increasing patch version here to point to latest safe_core 9 | 10 | #[0.6.0] 11 | - Integrating with safe_core with it's updated API (error FFI values have changed) 12 | 13 | #[0.5.0] 14 | - Logging facility added and tested 15 | 16 | #[0.4.5] 17 | - Revert safe_core back to 0.9.0 18 | 19 | #[0.4.4] 20 | - Dependency version updates 21 | 22 | #[0.4.3] 23 | - Upgrade for safe_core 0.9.0 24 | 25 | #[0.4.2] 26 | - Upgrade for safe_core 0.8.0 27 | 28 | #[0.4.1] 29 | - version update for safe_nfs & safe_core 30 | 31 | #[0.4.0] 32 | - NFS API added 33 | - DNS API added 34 | -------------------------------------------------------------------------------- /CONTRIBUTOR: -------------------------------------------------------------------------------- 1 | MaidSafe Contributor Agreement version 1.1 2 | 3 | 1. Scope of this Agreement 4 | 5 | This MaidSafe Contributor Agreement ("MCA") applies to any accepted contribution (as defined below) 6 | that you make to any software or other product or project managed by us (the "project"), and sets 7 | out the intellectual property rights you assign and grant to us in the contributed materials. 8 | The term "us" shall mean MaidSafe.net Limited. The term "you" shall mean the person or entity 9 | identified below. 10 | 11 | 12 | 2. Acceptance 13 | 14 | You should read this agreement carefully before posting any contributions (as defined below) to the 15 | project. Your posting of any contribution to this project will be deemed to constitute acceptance 16 | of the terms of this MCA. This MCA is a binding legal agreement between you and us. 17 | 18 | 19 | 3. Intellectual property rights 20 | 21 | The term "contributions" or "contributed materials" means any source code, object code, patch, tool, 22 | sample, graphic, specification, manual, documentation, or any other material posted or submitted by 23 | you to the project. 24 | 25 | The term "intellectual property rights" means any patents, rights to inventions, copyrights and 26 | similar rights, rights in know-how and all other intellectual property rights anywhere in the world 27 | for the full term of those rights including all registrations and applications and the right to 28 | apply for registrations. 29 | 30 | In relation to intellectual property rights in your contributions: 31 | 32 | * you hereby assign to us with full title guarantee all the intellectual property rights 33 | (existing and future) in your contributions (the "rights"), and we hereby grant to you a 34 | perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free, unrestricted 35 | license to use the rights for any purpose. To the extent that such assignment is or becomes 36 | invalid, ineffective or unenforceable, you hereby grant to us a perpetual, irrevocable, 37 | non-exclusive, worldwide, no-charge, royalty-free, unrestricted license to use the rights for 38 | any purpose (including, at our option, the right to sublicense these same rights to third 39 | parties through multiple levels of sublicensees or other licensing arrangements. 40 | 41 | * you hereby irrevocably and unconditionally waive all moral rights which you may have in your 42 | contributions in whatever part of the world such rights may be enforceable; 43 | 44 | * you agree to, without charge, execute and do all such acts, documents, matters and things as 45 | may be necessary or reasonably required to obtain patent, copyright or other protection for 46 | any of your contributions (or software in which they are included) or improvements or 47 | developments to them and to vest title to the intellectual property rights in them in us and 48 | you irrevocably appoint us to be your attorney and in your name and on your behalf to execute 49 | and do any such acts described above for the same purpose if needed; and 50 | 51 | * you agree that neither of us has any duty to consult with, obtain the consent of, pay or 52 | render an accounting to the other for any use or distribution of your contribution. 53 | 54 | This MCA is effective on the date you first submitted a contribution to us. Any contribution we 55 | make available under any license will also be made available under GPL v3. 56 | 57 | You covenant, represent, warrant and agree that: 58 | 59 | * each contribution that you submit (1) is and shall be an original work of authorship and you 60 | can legally assign and grant the rights set out in this MCA, and (2) does not include any 61 | third party code or other materials; 62 | 63 | * no contribution will violate any third party's intellectual property rights; and 64 | 65 | * each contribution shall be in compliance with (and will not need a licence or permission 66 | under) applicable export or import laws. 67 | 68 | You agree to notify us if you become aware of any circumstance which would make any of the foregoing 69 | representations inaccurate in any respect. MaidSafe may publicly disclose your participation in the 70 | project, including the fact that you have signed the MCA. 71 | 72 | Any notice or other written communication to be given under or in connection with this agreement 73 | shall be in writing, no term shall be varied by statement, conduct or act of any party except that 74 | the parties may amend this agreement only by letter or written instrument signed by both parties. 75 | This agreement sets out the entire agreement and understanding between the parties relating to your 76 | contributions. 77 | 78 | This MCA is governed by Scottish law and subject to the jurisdiction of the Scottish courts save 79 | that we or you may bring action in other courts to the extent necessary to protect or enforce our 80 | intellectual property rights. 81 | 82 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["MaidSafe Developers "] 3 | description = "SAFE API - FFI library" 4 | documentation = "http://maidsafe.github.io/safe_ffi/latest/" 5 | homepage = "http://maidsafe.net" 6 | license = "GPL-3.0" 7 | name = "safe_ffi" 8 | readme = "README.md" 9 | repository = "https://github.com/maidsafe/safe_ffi" 10 | version = "0.6.2" 11 | 12 | [dependencies] 13 | libc = "~0.2.10" 14 | log = "~0.3.6" 15 | maidsafe_utilities = "~0.5.3" 16 | rustc-serialize = "~0.3.19" 17 | safe_core = "~0.14.3" 18 | sodiumoxide = "~0.0.10" 19 | xor_name = "~0.1.0" 20 | 21 | [dependencies.clippy] 22 | optional = true 23 | version = "~0.0.63" 24 | 25 | [features] 26 | use-mock-routing = ["safe_core/use-mock-routing"] 27 | 28 | [lib] 29 | crate_type = ["staticlib", "dylib", "rlib"] 30 | name = "safe_ffi" 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MaidSafe.net Commercial Licence 1.0 2 | 3 | DATE [insert date] 4 | 5 | 6 | PARTIES 7 | 8 | (1) MaidSafe.next Ltd registered company number SC297540 of 72 Templehill, Troon, Scotland, 9 | KA10 6BE; and 10 | 11 | (2) [INSERT FULL COMPANY NAME OF CUSTOMER] (registered company number [number]) of [address] 12 | (the "Customer"). 13 | 14 | 15 | INTRODUCTION 16 | 17 | MaidSafe has agreed to supply and license, and the Customer has agreed to use and pay for, 18 | MaidSafe's proprietary software on the terms set out in this agreement. 19 | 20 | 21 | 1. Definitions 22 | 23 | In this agreement: 24 | 25 | "Affiliate" means in relation to any company, any body corporate which is from time to time a 26 | holding company of that company, a subsidiary of that company or a subsidiary of a holding 27 | company of that company ("holding company" and "subsidiary" having the meanings attributed to 28 | them by s.1159 Companies Act 2006); 29 | 30 | "Intellectual Property Rights" means any patents, rights to inventions, copyrights and similar 31 | rights, rights in know-how and all other intellectual property rights anywhere in the world 32 | for the full term of those rights including all registrations and applications and the right 33 | to apply for registrations; 34 | 35 | "Licence" shall mean the licence in clause 3 of this agreement; 36 | 37 | "Object" form shall mean any form resulting from mechanical transformation or translation of a 38 | Source form, including but not limited to compiled object code, generated documentation, and 39 | conversions to other media types; 40 | 41 | "Software" means the source or binary form of any MaidSafe.net limited developed code; and 42 | 43 | "Source" form shall mean software source code. 44 | 45 | 46 | 2. Supply of the Software 47 | 48 | MaidSafe will make available to the Customer the Software for download. 49 | 50 | 51 | 3. Licence 52 | 53 | 3.1 In consideration of, and subject to payment of, the charges payable under this agreement, 54 | MaidSafe grants the Customer a perpetual non-exclusive licence to use reproduce, sublicense, 55 | and distribute the Software in Source or Object form, in each case in accordance with this 56 | clause 3, for the duration of this agreement. This right includes the right to use the 57 | Intellectual Property Rights in the Software, including patent rights, and the Customer 58 | acknowledges that its use of the Software or any similar software (or any modified version of 59 | the Software or any software that is based on or includes any part of the Software) other than 60 | in accordance with the terms of this agreement (including the payment of the charges when due) 61 | would infringe MaidSafe's Intellectual Property Rights, including patents rights, and in such 62 | cases MaidSafe may terminate this Agreement without prejudice to its rights to claim damages, 63 | account of profits and/or injunctive relief. 64 | 65 | 3.2 Customer may reproduce and distribute copies of the Software in any medium, with or without 66 | modifications, and in Source or Object form, provided that Customer meets the following 67 | conditions: 68 | 69 | (a) Customer must ensure that any permitted user is required to enter into a written 70 | software licence and is not allowed to use the Software (including any modified version 71 | of the Software or any software that is based on or includes any part of the Software) 72 | in any manner that would not be permitted by this Licence; 73 | 74 | (b) Customer must cause any modified files to carry prominent notices stating that Customer 75 | changed the files; 76 | 77 | (c) Customer must retain, in the Source form of any copies of the Software (including any 78 | modified version of the Software or any software that is based on or includes any part 79 | of the Software) or any part thereof that Customer distributes, all copyright, patent, 80 | trademark, and attribution notices from the Source form of the Software; and 81 | 82 | (d) if the Software includes a "NOTICE" text file as part of its distribution, then any 83 | copies of the Software (including any modified version of the Software or any software 84 | that is based on or includes any part of the Software) or any part that Customer 85 | distributes must include a readable copy of the attribution notices contained within 86 | such NOTICE file in at least one of the following places: 87 | 88 | (i) within a NOTICE text file distributed as part of the Software; 89 | 90 | (ii) within the Source form or documentation, if provided along with the Software; or 91 | 92 | (iii) within a display generated by the Software, if and wherever such third-party 93 | notices normally appear. The contents of the NOTICE file are for informational 94 | purposes only and do not modify the Licence. 95 | 96 | 3.3 Except as expressly permitted otherwise by any term of this agreement, only the Customer is 97 | permitted to use the Software. Use by the Customer includes use by the Customer's employees 98 | and contractors provided that such use is solely on behalf of the Customer and for the 99 | purposes of the Customer's business. 100 | 101 | 3.4 The Customer may make such backup copies of the Software as are reasonably necessary to 102 | support the Customer's use of the Software in accordance with this agreement. MaidSafe will 103 | own the Intellectual Property Rights in any such backup copies. 104 | 105 | 3.5 The Customer may reverse engineer or decompile the Software but only to the extent allowed 106 | under applicable law and on the basis that Customer will request interoperability information 107 | from MaidSafe. 108 | 109 | 3.6 The Customer will comply with any reasonable instructions which MaidSafe gives the Customer 110 | relating to the use of the Software (or any modified version of the Software or any software 111 | that is based on or includes any part of the Software). The Customer will allow MaidSafe 112 | access to any premises controlled by the Customer in order to allow MaidSafe to check that the 113 | Software (or any modified version of the Software or any software that is based on or includes 114 | any part of the Software) is being used only as permitted. 115 | 116 | 3.7 This agreement does not grant permission to use the trade names, trademarks, service marks, or 117 | product names of the Licensor, except as required for reasonable and customary use in 118 | describing the origin of the Software and complying with this agreement. 119 | 120 | 121 | 4. Limited warranty 122 | 123 | 4.1 MaidSafe warrants that it will perform its obligations under this agreement with reasonable 124 | care and skill. 125 | 126 | 4.2 If the warranty in clause 4.1 is breached, the Customer must tell MaidSafe as soon as 127 | possible. The Customer must give MaidSafe a reasonable time to fix the problem or to 128 | re-perform any relevant services. This will be done without any additional charge to the 129 | Customer. If MaidSafe is able to do this within a reasonable time, MaidSafe will have no 130 | other obligations or liability in relation to that breach. If MaidSafe is unable to do this 131 | within a reasonable time or MaidSafe does not think that it is a sensible way to deal with the 132 | problem, then MaidSafe may if it wishes elect to take back the Software and to refund to the 133 | Customer all of the money which the Customer has paid to MaidSafe under this agreement. Where 134 | the problem relates to a portion of the Software and other elements supplied which are capable 135 | of use separately without material detriment to the Customer, MaidSafe may take back (and 136 | refund in respect of) affected portions only. 137 | 138 | 4.3 Apart from the terms set out in this agreement, no conditions, warranties or other terms apply 139 | to the Software or its supply or Licence under this agreement. In particular, no implied 140 | conditions, warranties or other terms relating to satisfactory quality or fitness for any 141 | purpose will apply to anything supplied under this agreement. MaidSafe does not warrant or 142 | enter into any terms to the effect that the Software: 143 | 144 | (a) will perform any particular function or purpose; or 145 | 146 | (b) be entirely free from defects or that its operation will be entirely error free. 147 | 148 | 4.4 MaidSafe will not be liable for breach of any of the warranties or any other terms in this 149 | agreement to the extent that the breach arises from: 150 | 151 | (a) use of the Software other than in accordance with normal operating procedures or as 152 | otherwise notified to the Customer by MaidSafe; 153 | 154 | (b) any alterations to the Software made by anyone other than MaidSafe or someone authorised 155 | by MaidSafe; 156 | 157 | (c) any problem with the computer on which the Software is installed, any equipment 158 | connected to that computer or any other software which is installed on that computer; 159 | 160 | (d) any abnormal or incorrect operating conditions; or 161 | 162 | (e) use of the Software in combination with any other hardware or software, unless this use 163 | has been approved by MaidSafe in writing. 164 | 165 | 166 | 5. Limitation of Liability 167 | 168 | 5.1 Neither party's liability: 169 | 170 | (a) for death or personal injury caused by its negligence or the negligence of its employees 171 | or agents; 172 | 173 | (b) for breach of clause 7 (Confidentiality); or 174 | 175 | (c) for fraudulent misrepresentation, is excluded or limited by this agreement, even if any 176 | other term of this agreement would otherwise suggest that this might be the case. 177 | 178 | 5.2 Other than as set out in clause 5.1, neither party shall be liable to the other (whether for 179 | breach of contract, negligence or for any other reason) for any: 180 | 181 | (a) loss of profits; 182 | 183 | (b) loss of sales; 184 | 185 | (c) loss of revenue; 186 | 187 | (d) loss of any software or data; 188 | 189 | (e) loss of use of hardware, software or data; 190 | 191 | (f) indirect, consequential or special loss. 192 | 193 | 5.3 Subject to clauses 5.1 and 5.2, MaidSafe's total aggregate liability under this agreement and 194 | in relation to anything which MaidSafe has done or not done in connection with this agreement 195 | (and whether the liability arises because of breach of contract, negligence or for any other 196 | reason) shall be limited to: 197 | 198 | (a) an amount equal to 125% of the total amount payable by the Customer under this agreement 199 | in the preceding 12 months; or 200 | 201 | (b) if the amount referred to in (a) cannot be calculated accurately at the time the 202 | relevant liability is to be assessed, or if it is less than £5,000, to £5,000 203 | 204 | 205 | 6. Charges 206 | 207 | 6.1 Schedule 1 sets out the licence fees and other charges payable by the Customer under this 208 | agreement. The charges are due on the dates (or on the happening of the events) specified in 209 | schedule 1. 210 | 211 | 6.2 MaidSafe may invoice the Customer for the charges as soon as they become due. The Customer 212 | must pay the invoices within 30 days of receiving them (and if MaidSafe posts them to the 213 | Customer, the Customer will be treated as having received them two working days later unless 214 | the Customer can show that this was not the case). 215 | 216 | 6.3 Where any charges are based on the Customer's revenues the Customer shall keep all accounts 217 | and documents necessary to evidence such revenues and to support any calculation of the 218 | relevant revenue share, and shall provide copies to MaidSafe on request. Customer shall allow 219 | MaidSafe and its agents to enter into Customer's premises and to have access to all such 220 | accounts and documents upon reasonable request. Where Customer's accounts and documents 221 | illustrate that Customer has underpaid any charges (or MaidSafe can otherwise demonstrate 222 | this) Customer shall immediately pay the balance due to MaidSafe plus MaidSafe's reasonable 223 | costs of audit. This clause 6.3 shall survive termination or expiry of this agreement for 6 224 | years. 225 | 226 | 6.4 MaidSafe may charge interest on all sums outstanding beyond the date on which they are due for 227 | payment under this agreement. Interest may be charged on that basis from the date payment was 228 | due until the date of payment (including after any judgement has been obtained) at the rate of 229 | 3% per calendar month or part thereof. 230 | 231 | 6.5 The amounts specified in schedule 1 do not include VAT or any other taxes on supplies and the 232 | Customer will pay these to MaidSafe as well as the amounts concerned. 233 | 234 | 235 | 7. Confidentiality 236 | 237 | 7.1 Each party will keep confidential any information which the other supplies to it in connection 238 | with this agreement. Confidential information will include the Software and any related 239 | documentation; all information marked as being confidential; and any other information which 240 | might reasonably be assumed to be confidential. The obligations as to confidentiality in this 241 | agreement will not apply to any information which: 242 | 243 | (a) is available to the public other than because of any breach of this agreement; 244 | 245 | (b) is, when it is supplied, already known to whomever it is disclosed to in circumstances 246 | in which they are not prevented from disclosing it to others; 247 | 248 | (c) is independently obtained by whomever it is disclosed to in circumstances in which they 249 | are not prevented from disclosing it to others; or 250 | 251 | (d) is required to be disclosed by law or by any court or tribunal with proper authority to 252 | order its disclosure (but only to the extent of such requirements). 253 | 254 | 255 | 8. Term and termination 256 | 257 | 8.1 This agreement will commence on the date set out on page 1 and will continue indefinitely 258 | until terminated in accordance with this clause 8. 259 | 260 | 8.2 Either party may terminate this agreement if: 261 | 262 | (a) the other materially breaches any term of this agreement and it is not possible to 263 | remedy that breach or it is possible to remedy that breach, but the other fails to do so 264 | within 30 days of being asked to do so; or 265 | 266 | (b) the other suffers any of the following event: 267 | 268 | (i) a meeting of creditors of that party being held or an arrangement or composition 269 | with or for the benefit of its creditors (including a voluntary arrangement as 270 | defined in the Insolvency Act 1986) being proposed by or in relation to that 271 | party; 272 | 273 | (ii) a chargeholder, receiver, administrative receiver or other similar party taking 274 | possession of or being appointed over or any distress, execution or other process 275 | being levied or enforced (and not being discharged within seven days) on the whole 276 | or a material part of the assets of that party; 277 | 278 | (iii) that party ceasing to carry on business or being deemed to be unable to pay its 279 | debts within the meaning of section 123 Insolvency Act 1986; 280 | 281 | (iv) that party or its directors or the holder of a qualifying floating charge or any 282 | of its creditors giving notice of their intention to appoint, appointing or making 283 | an application to the court for the appointment of, an administrator; 284 | 285 | (v) a petition being advertised or a resolution being passed or an order being made 286 | for the administration or the winding-up, bankruptcy or dissolution of that party; 287 | and/or 288 | 289 | (vi) the happening in relation to that party of an event analogous to any of the above 290 | in any jurisdiction in which it is incorporated or resident or in which it carries 291 | on business or has assets. 292 | 293 | 8.3 MaidSafe may terminate this agreement if: 294 | 295 | (a) Customer fails to pay any charges within 60 days of their due date; or 296 | 297 | (b) should the Software become, or in MaidSafe's reasonable opinion is likely to become, the 298 | subject of a claim of intellectual property infringement claim. 299 | 300 | 8.4 Apart from any other rights which MaidSafe might have, if the Customer breaches this agreement 301 | MaidSafe may suspend performance of any of its obligations or any of the Customer's rights 302 | under this agreement until the Customer remedies the breach to the reasonable satisfaction of 303 | MaidSafe. 304 | 305 | 306 | 9. Consequences of termination 307 | 308 | 9.1 If this agreement is terminated (regardless of who terminates it and regardless of the reason) 309 | the Customer will immediately on termination: 310 | 311 | (a) cease using the Software (including any modified version of the Software or any software 312 | that is based on or includes any part of the Software); 313 | 314 | (b) return all copies of the Software to MaidSafe or (if the copies are on media which is 315 | non-removable and forms part of equipment belonging to the Customer) delete all copies 316 | in such a way that they cannot be recovered; and 317 | 318 | (c) confirm to MaidSafe in writing that both of the above things have been done. 319 | 320 | 9.2 Termination of this agreement will not affect any accrued rights or liabilities which either 321 | MaidSafe or the Customer may have by the time termination takes effect. Clauses 5, 6 (for 322 | unpaid charges), 7 and 9 shall survive termination or expiry of this agreement and any other 323 | clause shall survive termination or expiry if expressly stated. 324 | 325 | 326 | 10. Other terms 327 | 328 | 10.1 The Customer may not assign any of the Customer's rights or obligations under this agreement. 329 | MaidSafe may assign this agreement or any of MaidSafe's rights or obligations under this 330 | agreement to someone else, provided MaidSafe tells the Customer in writing if it does so. 331 | 332 | 10.2 Neither party has any authority to enter into a contract for or on behalf of the other party, 333 | to assume a liability on behalf of the other party or to pledge the credit of the other party, 334 | unless such authority is expressly granted in writing by the other party. Neither party may 335 | act as if it has such authority and must not represent (expressly or by implying it) that it 336 | has such authority. 337 | 338 | 10.3 MaidSafe will not be liable to the Customer for any breach of this agreement which arises 339 | because of any circumstances which MaidSafe cannot reasonably be expected to control. 340 | 341 | 10.4 All notices and consents relating to this agreement must be in writing. All variations to 342 | this agreement must be agreed, set out in writing and signed on behalf of both MaidSafe and 343 | the Customer before they take effect. 344 | 345 | 10.5 In this agreement, unless it says otherwise: 346 | 347 | (a) reference to a person includes a legal person (such as a limited company) as well as a 348 | natural person; 349 | 350 | (b) reference to this agreement includes reference to the schedules and appendices and other 351 | documents attached to it or incorporated by reference into it (all as amended or added 352 | to from time to time); 353 | 354 | (c) reference to "including" in this agreement shall be treated as being by way of example 355 | and shall not limit the general applicability of any preceding words; 356 | 357 | (d) reference to any legislation shall be to that legislation as amended, extended or 358 | re-enacted from time to time and to any subordinate provision made under that 359 | legislation; 360 | 361 | (e) references to clauses or schedules shall be to those in this agreement; 362 | 363 | (f) reference to this agreement shall include reference to it after it has been amended, 364 | added to or replaced by a new agreement. 365 | 366 | 10.6 Except to the extent that this agreement expressly says otherwise, nothing in this agreement 367 | shall create a partnership between the parties or give the rights of a partner to either 368 | party. 369 | 370 | 10.7 Any software supplied or Licenced under this agreement will not be treated as goods within the 371 | meaning of the Sale of Goods Act 1979. Firmware will be treated as part of the goods in which 372 | it is installed. 373 | 374 | 10.8 This agreement sets out all of the terms that have been agreed between MaidSafe and the 375 | Customer in relation to the subjects covered by it. Subject to clause 5.1, no other 376 | representations or terms shall apply or form part of this agreement. The Customer 377 | acknowledges that it has not been influenced to enter this agreement by anything MaidSafe has 378 | said or done or committed to do, except as expressly recorded herein. 379 | 380 | 10.9 No term of this agreement is enforceable under the Contracts (Rights of Third Parties) Act 381 | 1999 by a person who is not a party to this agreement. 382 | 383 | 10.10 This agreement is governed by Scottish law. Both MaidSafe and the Customer submit to the 384 | exclusive jurisdiction of the Scottish courts in relation to any dispute concerning this 385 | agreement but MaidSafe is also entitled to apply to any court worldwide for injunctive and 386 | other remedies in order to protect or enforce its Intellectual Property Rights. 387 | 388 | 389 | SCHEDULE 1 390 | 391 | CHARGES 392 | 393 | 394 | 1. Customer shall pay to MaidSafe 1% of Qualifying Revenue. 395 | 396 | 2 "Qualifying Revenue" shall mean any revenue generated directly or indirectly by Customer or 397 | any Affiliate of Customer through: 398 | 399 | (a) use of the Software (including any modified version of the Software or any software that 400 | is based on or includes any part of the Software); or 401 | 402 | (b) the provision of services directly or indirectly to any person using the Software 403 | (including any modified version of the Software or any software that is based on or 404 | includes any part of the Software), 405 | 406 | ("Qualifying Activities") less any VAT charged on such Qualifying Activities. 407 | 408 | 3. Where any Qualifying Activity is discounted or provided for free (whether through bundling or 409 | otherwise) it will be deemed to be provided at market rate and the relevant Qualifying Revenue 410 | shall be calculated accordingly. 411 | 412 | 4. The charges will be payable quarterly in arrears. 413 | 414 | 5. Within 5 days of the end of each month Customer will provide to MaidSafe a statement setting 415 | out the Qualifying Revenue for the month. MaidSafe shall invoice Customer within 5 days of 416 | the end of each third month. Where no statement is provided or MaidSafe has cause to believe 417 | it to be inaccurate it may invoke its audit rights under this agreement. 418 | 419 | 420 | SIGNED on behalf of both parties on the date set out on page 1 of this agreement: 421 | 422 | 423 | 424 | SIGNED: ..................................................................... 425 | for and on behalf of MaidSafe 426 | 427 | 428 | 429 | ..................................................................... 430 | Name/status 431 | 432 | 433 | 434 | 435 | SIGNED: ..................................................................... 436 | for and on behalf of the Customer 437 | 438 | 439 | 440 | ..................................................................... 441 | Name/status 442 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ***This repository is no longer maintained*** 2 | # It has been moved to the maidsafe-archive organisation for reference only 3 | # 4 | # 5 | # 6 | # 7 | # safe_ffi 8 | 9 | [![](https://img.shields.io/badge/Project%20SAFE-Approved-green.svg)](http://maidsafe.net/applications) [![](https://img.shields.io/badge/License-GPL3-green.svg)](https://github.com/maidsafe/safe_ffi/blob/master/COPYING) 10 | 11 | 12 | **Primary Maintainer:** Spandan Sharma (spandan.sharma@maidsafe.net) 13 | 14 | **Secondary Maintainer:** Krishna Kumar (krishna.kumar@maidsafe.net) 15 | 16 | |Linux/OS X|Windows|Coverage|Issues| 17 | |:--------:|:-----:|:------:|:----:| 18 | |[![Build Status](https://travis-ci.org/maidsafe/safe_ffi.svg?branch=master)](https://travis-ci.org/maidsafe/safe_ffi)|[![Build status](https://ci.appveyor.com/api/projects/status/5nqc5h06v3vsp2ad/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-ffi/branch/master)|[![Coverage Status](https://coveralls.io/repos/maidsafe/safe_ffi/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/safe_ffi?branch=master)|[![Stories in Ready](https://badge.waffle.io/maidsafe/safe_ffi.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_ffi)| 19 | 20 | | [API Documentation - master branch](http://maidsafe.net/safe_ffi/master) | [SAFE Network System Documentation](http://systemdocs.maidsafe.net) | [MaidSafe website](http://maidsafe.net) | [SAFE Network Forum](https://forum.safenetwork.io) | 21 | |:------:|:-------:|:-------:|:-------:| 22 | 23 | ## Prerequisite 24 | 25 | [libsodium](https://github.com/jedisct1/libsodium) is a native dependency, and can be installed by following the instructions [for Windows](https://github.com/maidsafe/QA/blob/master/Documentation/Install%20libsodium%20for%20Windows.md) or [for OS X and Linux](https://github.com/maidsafe/QA/blob/master/Documentation/Install%20libsodium%20for%20OS%20X%20or%20Linux.md). 26 | 27 | ## Build Instructions 28 | 29 | `safe_ffi` can interface with Client modules conditionally built against either the routing crate or a mock used for local testing. 30 | 31 | To use it with the Mock: 32 | ``` 33 | cargo build --features "use-mock-routing" 34 | cargo test --features "use-mock-routing" 35 | ``` 36 | 37 | To interface it with actual routing (default): 38 | ``` 39 | cargo build 40 | cargo test 41 | ``` 42 | 43 | ## Todo Items 44 | 45 | - [ ] Expand scope of test cases 46 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | global: 3 | RUST_BACKTRACE: 1 4 | Features: "use-mock-routing" 5 | matrix: 6 | - RUST_VERSION: stable 7 | branches: 8 | only: 9 | - master 10 | 11 | clone_depth: 50 12 | 13 | install: 14 | - ps: | 15 | $url = "https://github.com/maidsafe/QA/raw/master/Powershell%20Scripts/AppVeyor" 16 | Start-FileDownload "$url/Install%20Rust.ps1" -FileName "Install Rust.ps1" 17 | Start-FileDownload "$url/Install%20MinGW.ps1" -FileName "Install MinGW.ps1" 18 | Start-FileDownload "$url/Install%20libsodium.ps1" -FileName "Install libsodium.ps1" 19 | Start-FileDownload "$url/Build.ps1" -FileName "Build.ps1" 20 | Start-FileDownload "$url/Run%20Tests.ps1" -FileName "Run Tests.ps1" 21 | . ".\Install Rust.ps1" 22 | . ".\Install MinGW.ps1" 23 | . ".\Install libsodium.ps1" 24 | 25 | platform: 26 | - x86 27 | - x64 28 | 29 | configuration: 30 | # - Debug 31 | - Release 32 | 33 | # Allowing failures for x86 to accommodate for current libsodium test failure in x86 34 | matrix: 35 | allow_failures: 36 | - platform: x86 37 | 38 | build_script: 39 | - ps: . ".\Build.ps1" 40 | 41 | test_script: 42 | - ps: . ".\Run Tests.ps1" 43 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | 19 | pub const SAFE_DRIVE_DIR_NAME: &'static str = "SAFEDrive"; 20 | pub const LAUNCHER_GLOBAL_DIRECTORY_NAME: &'static str = "LauncherReservedDirectory"; 21 | pub const LAUNCHER_GLOBAL_CONFIG_FILE_NAME: &'static str = "LauncherSpecificConfigurationFile"; 22 | 23 | use rustc_serialize::base64::{CharacterSet, Config, Newline}; 24 | 25 | pub fn get_base64_config() -> Config { 26 | Config { 27 | char_set: CharacterSet::Standard, 28 | newline: Newline::LF, 29 | pad: true, 30 | line_length: None, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/dns/add_service.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::dns::dns_operations::DnsOperations; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct AddService { 24 | pub long_name: String, 25 | pub service_name: String, 26 | pub is_path_shared: bool, 27 | pub service_home_dir_path: String, 28 | } 29 | 30 | impl Action for AddService { 31 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 32 | if self.is_path_shared && !params.safe_drive_access { 33 | return Err(FfiError::PermissionDenied); 34 | } 35 | 36 | let tokens = helper::tokenise_path(&self.service_home_dir_path, false); 37 | 38 | let start_dir_key = if self.is_path_shared { 39 | try!(params.safe_drive_dir_key 40 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 41 | } else { 42 | try!(params.app_root_dir_key 43 | .ok_or(FfiError::from("Application directory key is not present"))) 44 | }; 45 | 46 | let dir_to_map = try!(helper::get_final_subdirectory(params.client.clone(), 47 | &tokens, 48 | Some(&start_dir_key))); 49 | 50 | let signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()) 51 | .clone(); 52 | let dns_operation = try!(DnsOperations::new(params.client.clone())); 53 | try!(dns_operation.add_service(&self.long_name, 54 | (self.service_name.clone(), dir_to_map.get_key().clone()), 55 | &signing_key, 56 | None)); 57 | Ok(None) 58 | } 59 | } 60 | 61 | #[cfg(test)] 62 | mod test { 63 | use super::*; 64 | use dns::register_dns::RegisterDns; 65 | use Action; 66 | use test_utils; 67 | use safe_core::core::utility; 68 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 69 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 70 | 71 | const TEST_DIR_NAME: &'static str = "test_dir"; 72 | 73 | #[test] 74 | fn add_dns_service() { 75 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 76 | 77 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 78 | let ref app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 79 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 80 | let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), 81 | UNVERSIONED_DIRECTORY_LISTING_TAG, 82 | Vec::new(), 83 | false, 84 | AccessLevel::Public, 85 | Some(&mut app_root_dir))); 86 | let public_name = unwrap_result!(utility::generate_random_string(10)); 87 | let mut register_request = RegisterDns { 88 | long_name: public_name.clone(), 89 | service_name: "www".to_string(), 90 | is_path_shared: false, 91 | service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), 92 | }; 93 | assert!(register_request.execute(parameter_packet.clone()).is_ok()); 94 | 95 | let mut request = AddService { 96 | long_name: public_name, 97 | service_name: "blog".to_string(), 98 | is_path_shared: false, 99 | service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), 100 | }; 101 | 102 | assert!(request.execute(parameter_packet).is_ok()); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/dns/delete_dns.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use safe_core::dns::dns_operations::DnsOperations; 19 | use {ParameterPacket, ResponseType, Action}; 20 | 21 | #[derive(RustcDecodable, Debug)] 22 | pub struct DeleteDns { 23 | pub long_name: String, 24 | } 25 | 26 | impl Action for DeleteDns { 27 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 28 | let signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()) 29 | .clone(); 30 | let dns_ops = try!(DnsOperations::new(params.client)); 31 | let _ = try!(dns_ops.delete_dns(&self.long_name, &signing_key)); 32 | 33 | Ok(None) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/dns/delete_service.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use safe_core::dns::dns_operations::DnsOperations; 19 | use {ParameterPacket, ResponseType, Action}; 20 | 21 | #[derive(RustcDecodable, Debug)] 22 | pub struct DeleteService { 23 | pub long_name: String, 24 | pub service_name: String, 25 | } 26 | 27 | impl Action for DeleteService { 28 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 29 | let signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()) 30 | .clone(); 31 | let dns_ops = try!(DnsOperations::new(params.client)); 32 | let _ = try!(dns_ops.remove_service(&self.long_name, 33 | self.service_name.clone(), 34 | &signing_key, 35 | None)); 36 | 37 | Ok(None) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/dns/get_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use rustc_serialize::json; 20 | use nfs::file_response::get_response; 21 | use safe_core::dns::dns_operations::DnsOperations; 22 | use {helper, ParameterPacket, ResponseType, Action}; 23 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 24 | 25 | #[derive(RustcDecodable, Debug)] 26 | pub struct GetFile { 27 | pub long_name: String, 28 | pub service_name: String, 29 | pub offset: i64, 30 | pub length: i64, 31 | pub file_path: String, 32 | pub include_metadata: bool, 33 | } 34 | 35 | impl Action for GetFile { 36 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 37 | let dns_operations = match params.app_root_dir_key { 38 | Some(_) => try!(DnsOperations::new(params.client.clone())), 39 | None => DnsOperations::new_unregistered(params.client.clone()), 40 | }; 41 | let directory_key = try!(dns_operations.get_service_home_directory_key(&self.long_name, 42 | &self.service_name, 43 | None)); 44 | let mut tokens = helper::tokenise_path(&self.file_path, false); 45 | let file_name = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 46 | let file_dir = if tokens.len() > 0 { 47 | try!(helper::get_final_subdirectory(params.client.clone(), 48 | &tokens, 49 | Some(&directory_key))) 50 | } else { 51 | let dir_helper = DirectoryHelper::new(params.client.clone()); 52 | try!(dir_helper.get(&directory_key)) 53 | }; 54 | let file = try!(file_dir.find_file(&file_name) 55 | .ok_or(::errors::FfiError::InvalidPath)); 56 | let response = try!(get_response(file, 57 | params.client, 58 | self.offset, 59 | self.length, 60 | self.include_metadata)); 61 | 62 | Ok(Some(try!(json::encode(&response)))) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/dns/get_long_names.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use rustc_serialize::json; 19 | use safe_core::dns::dns_operations::DnsOperations; 20 | use {ParameterPacket, ResponseType, Action}; 21 | 22 | pub struct GetLongNames; 23 | 24 | impl Action for GetLongNames { 25 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 26 | let dns_ops = try!(DnsOperations::new(params.client)); 27 | let list = try!(dns_ops.get_all_registered_names()); 28 | 29 | Ok(Some(try!(json::encode(&list)))) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/dns/get_service_directory.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use {ParameterPacket, ResponseType, Action}; 19 | use safe_core::dns::dns_operations::DnsOperations; 20 | use nfs::directory_response; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct GetServiceDirectory { 24 | pub long_name: String, 25 | pub service_name: String, 26 | } 27 | 28 | impl Action for GetServiceDirectory { 29 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 30 | let dns_operations = match params.app_root_dir_key { 31 | Some(_) => try!(DnsOperations::new(params.client.clone())), 32 | None => DnsOperations::new_unregistered(params.client.clone()), 33 | }; 34 | let directory_key = try!(dns_operations.get_service_home_directory_key(&self.long_name, 35 | &self.service_name, 36 | None)); 37 | println!("Key {:?}", directory_key); 38 | let response = try!(directory_response::get_response(params.client, directory_key)); 39 | Ok(Some(try!(::rustc_serialize::json::encode(&response)))) 40 | } 41 | } 42 | 43 | 44 | #[cfg(test)] 45 | mod test { 46 | use super::*; 47 | use dns::add_service::AddService; 48 | use dns::register_dns::RegisterDns; 49 | use Action; 50 | use test_utils; 51 | use safe_core::core::utility; 52 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 53 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 54 | 55 | const TEST_DIR_NAME: &'static str = "test_dir"; 56 | 57 | #[test] 58 | fn get_service_directory() { 59 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 60 | 61 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 62 | let mut app_root_dir = 63 | unwrap_result!(dir_helper.get(&unwrap_option!(parameter_packet.clone() 64 | .app_root_dir_key, 65 | ""))); 66 | let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), 67 | UNVERSIONED_DIRECTORY_LISTING_TAG, 68 | Vec::new(), 69 | false, 70 | AccessLevel::Public, 71 | Some(&mut app_root_dir))); 72 | let public_name = unwrap_result!(utility::generate_random_string(10)); 73 | let mut register_request = RegisterDns { 74 | long_name: public_name.clone(), 75 | service_name: "www".to_string(), 76 | is_path_shared: false, 77 | service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), 78 | }; 79 | assert!(register_request.execute(parameter_packet.clone()).is_ok()); 80 | 81 | let mut request = AddService { 82 | long_name: public_name.clone(), 83 | service_name: "blog".to_string(), 84 | is_path_shared: false, 85 | service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), 86 | }; 87 | 88 | assert!(request.execute(parameter_packet.clone()).is_ok()); 89 | 90 | let mut get_service_directory_request = GetServiceDirectory { 91 | long_name: public_name, 92 | service_name: "www".to_string(), 93 | }; 94 | let parameter_packet_unregistered = 95 | unwrap_result!(test_utils::get_unregistered_parameter_packet()); 96 | let response = get_service_directory_request.execute(parameter_packet_unregistered); 97 | assert!(response.is_ok()); 98 | let response_json = unwrap_result!(response); 99 | assert!(response_json.is_some()); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/dns/get_services.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use rustc_serialize::json; 19 | use safe_core::dns::dns_operations::DnsOperations; 20 | use {ParameterPacket, ResponseType, Action}; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct GetServices { 24 | pub long_name: String, 25 | } 26 | 27 | impl Action for GetServices { 28 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 29 | let dns_ops = try!(DnsOperations::new(params.client)); 30 | let list = try!(dns_ops.get_all_services(&self.long_name, None)); 31 | 32 | Ok(Some(try!(json::encode(&list)))) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/dns/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | use std::fmt; 18 | 19 | use rustc_serialize::Decoder; 20 | use rustc_serialize::Decodable; 21 | use errors::FfiError; 22 | 23 | mod get_file; 24 | mod delete_dns; 25 | mod add_service; 26 | mod register_dns; 27 | mod get_services; 28 | mod get_long_names; 29 | mod delete_service; 30 | mod register_public_id; 31 | mod get_service_directory; 32 | 33 | pub fn action_dispatcher(action: String, 34 | params: ::ParameterPacket, 35 | decoder: &mut D) 36 | -> ::ResponseType 37 | where D: Decoder, 38 | D::Error: fmt::Debug 39 | { 40 | let mut action = try!(get_action(action, decoder)); 41 | action.execute(params) 42 | } 43 | 44 | fn get_action(action: String, decoder: &mut D) -> Result, FfiError> 45 | where D: Decoder, 46 | D::Error: fmt::Debug 47 | { 48 | Ok(match &action[..] { 49 | "register-public-id" => { 50 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 51 | register_public_id::RegisterPublicId::decode(d) 52 | }), 53 | ""))) 54 | } 55 | "register-dns" => { 56 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 57 | register_dns::RegisterDns::decode(d) 58 | }), 59 | ""))) 60 | } 61 | "add-service" => { 62 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 63 | add_service::AddService::decode(d) 64 | }), 65 | ""))) 66 | } 67 | "get-home-dir" => { 68 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 69 | get_service_directory::GetServiceDirectory::decode(d) 70 | }), 71 | ""))) 72 | } 73 | "get-file" => { 74 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 75 | get_file::GetFile::decode(d) 76 | }), 77 | ""))) 78 | } 79 | "get-long-names" => Box::new(get_long_names::GetLongNames), 80 | "get-services" => { 81 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 82 | get_services::GetServices::decode(d) 83 | }), 84 | ""))) 85 | } 86 | "delete-dns" => { 87 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 88 | delete_dns::DeleteDns::decode(d) 89 | }), 90 | ""))) 91 | } 92 | "delete-service" => { 93 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 94 | delete_service::DeleteService::decode(d) 95 | }), 96 | ""))) 97 | } 98 | _ => { 99 | return Err(FfiError::SpecificParseError(format!("Unsupported action {:?} for this \ 100 | endpoint.", 101 | action))) 102 | } 103 | }) 104 | } 105 | -------------------------------------------------------------------------------- /src/dns/register_dns.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use sodiumoxide::crypto::box_; 19 | 20 | use errors::FfiError; 21 | use safe_core::dns::dns_operations::DnsOperations; 22 | 23 | #[derive(RustcDecodable, Debug)] 24 | pub struct RegisterDns { 25 | pub long_name: String, 26 | pub service_name: String, 27 | pub is_path_shared: bool, 28 | pub service_home_dir_path: String, 29 | } 30 | 31 | impl ::Action for RegisterDns { 32 | fn execute(&mut self, params: ::ParameterPacket) -> ::ResponseType { 33 | if self.is_path_shared && !params.safe_drive_access { 34 | return Err(FfiError::PermissionDenied); 35 | } 36 | 37 | let tokens = ::helper::tokenise_path(&self.service_home_dir_path, false); 38 | 39 | let start_dir_key = if self.is_path_shared { 40 | try!(params.safe_drive_dir_key 41 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 42 | } else { 43 | try!(params.app_root_dir_key 44 | .ok_or(FfiError::from("Application directory key is not present"))) 45 | }; 46 | 47 | let dir_to_map = try!(::helper::get_final_subdirectory(params.client.clone(), 48 | &tokens, 49 | Some(&start_dir_key))); 50 | 51 | let (msg_public_key, msg_secret_key) = box_::gen_keypair(); 52 | let services = vec![(self.service_name.clone(), (dir_to_map.get_key().clone()))]; 53 | let public_signing_key = try!(unwrap_result!(params.client.lock()) 54 | .get_public_signing_key()) 55 | .clone(); 56 | let secret_signing_key = try!(unwrap_result!(params.client.lock()) 57 | .get_secret_signing_key()) 58 | .clone(); 59 | let dns_operation = try!(DnsOperations::new(params.client 60 | .clone())); 61 | try!(dns_operation.register_dns(self.long_name.clone(), 62 | &msg_public_key, 63 | &msg_secret_key, 64 | &services, 65 | vec![public_signing_key], 66 | &secret_signing_key, 67 | None)); 68 | Ok(None) 69 | } 70 | } 71 | 72 | #[cfg(test)] 73 | mod test { 74 | use super::*; 75 | use Action; 76 | use test_utils::get_parameter_packet; 77 | use safe_core::core::utility; 78 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 79 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 80 | 81 | const TEST_DIR_NAME: &'static str = "test_dir"; 82 | 83 | #[test] 84 | fn register_dns() { 85 | let parameter_packet = unwrap_result!(get_parameter_packet(false)); 86 | 87 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 88 | let mut app_root_dir = 89 | unwrap_result!(dir_helper.get(&unwrap_option!(parameter_packet.clone() 90 | .app_root_dir_key, 91 | ""))); 92 | let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), 93 | UNVERSIONED_DIRECTORY_LISTING_TAG, 94 | Vec::new(), 95 | false, 96 | AccessLevel::Public, 97 | Some(&mut app_root_dir))); 98 | let public_name = unwrap_result!(utility::generate_random_string(10)); 99 | let mut request = RegisterDns { 100 | long_name: public_name, 101 | service_name: "www".to_string(), 102 | is_path_shared: false, 103 | service_home_dir_path: "/test_dir2".to_string(), 104 | }; 105 | assert!(request.execute(parameter_packet.clone()).is_err()); 106 | request.service_home_dir_path = format!("/{}", TEST_DIR_NAME); 107 | assert!(request.execute(parameter_packet).is_ok()); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/dns/register_public_id.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use sodiumoxide::crypto::box_; 19 | use safe_core::dns::dns_operations::DnsOperations; 20 | 21 | #[derive(RustcDecodable, Debug)] 22 | pub struct RegisterPublicId { 23 | pub long_name: String, 24 | } 25 | 26 | impl ::Action for RegisterPublicId { 27 | fn execute(&mut self, params: ::ParameterPacket) -> ::ResponseType { 28 | let (msg_public_key, msg_secret_key) = box_::gen_keypair(); 29 | let services = vec![]; 30 | let public_signing_key = try!(unwrap_result!(params.client.lock()) 31 | .get_public_signing_key()) 32 | .clone(); 33 | let secret_signing_key = try!(unwrap_result!(params.client.lock()) 34 | .get_secret_signing_key()) 35 | .clone(); 36 | let dns_operation = try!(DnsOperations::new(params.client 37 | .clone())); 38 | try!(dns_operation.register_dns(self.long_name.clone(), 39 | &msg_public_key, 40 | &msg_secret_key, 41 | &services, 42 | vec![public_signing_key], 43 | &secret_signing_key, 44 | None)); 45 | Ok(None) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test { 51 | use super::*; 52 | use Action; 53 | use test_utils::get_parameter_packet; 54 | use safe_core::core::utility; 55 | 56 | #[test] 57 | fn register_public_id() { 58 | let parameter_packet = unwrap_result!(get_parameter_packet(false)); 59 | let public_name = unwrap_result!(utility::generate_random_string(10)); 60 | let mut request = RegisterPublicId { long_name: public_name.clone() }; 61 | assert!(request.execute(parameter_packet.clone()).is_ok()); 62 | // let parameter_packet = unwrap_result!(get_parameter_packet(false)); 63 | // let mut request = RegisterPublicId { long_name: public_name }; 64 | // assert!(request.execute(parameter_packet.clone()).is_err()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use std::fmt; 19 | 20 | use rustc_serialize::{json, base64}; 21 | 22 | use safe_core::core::errors::CoreError; 23 | use safe_core::dns::errors::{DNS_ERROR_START_RANGE, DnsError}; 24 | use safe_core::nfs::errors::NfsError; 25 | 26 | use maidsafe_utilities::serialisation::SerialisationError; 27 | 28 | /// Intended for converting Launcher Errors into numeric codes for propagating some error 29 | /// information across FFI boundaries and specially to C. 30 | pub const FFI_ERROR_START_RANGE: i32 = DNS_ERROR_START_RANGE - 500; 31 | 32 | /// Launcher Errors 33 | pub enum FfiError { 34 | /// Error from safe_core. Boxed to hold a pointer instead of value so that this enum variant is 35 | /// not insanely bigger than others. 36 | CoreError(Box), 37 | /// Errors from safe_nfs 38 | NfsError(Box), 39 | /// Errors from safe_nfs 40 | DnsError(Box), 41 | /// Unable to find/traverse directory or file path 42 | PathNotFound, 43 | /// Supplied path was invalid 44 | InvalidPath, 45 | /// Permission denied - e.g. permission to access SAFEDrive etc. 46 | PermissionDenied, 47 | /// Could not parse payload as a valid JSON 48 | JsonParseError(json::ParserError), 49 | /// Could not decode valid JSON into expected Structures probably because a mandatory field was 50 | /// missing or a field was wrongly named etc. 51 | JsonDecodeError(json::DecoderError), 52 | /// JSON non-conforming to the Launcher RFC and not covered by JsonDecodeError, e.g. things 53 | /// like invalid base64 formatting, unreasonable/unexpected indexing, ranges etc. 54 | SpecificParseError(String), 55 | /// Error encoding into Json String 56 | JsonEncodeError(json::EncoderError), 57 | /// Unable to Read from or Write to a Local Config file. 58 | LocalConfigAccessFailed(String), 59 | /// Unexpected - Probably a Logic error 60 | Unexpected(String), 61 | /// Could not serialise or deserialise data 62 | UnsuccessfulEncodeDecode(SerialisationError), 63 | } 64 | 65 | impl From for FfiError { 66 | fn from(error: SerialisationError) -> FfiError { 67 | FfiError::UnsuccessfulEncodeDecode(error) 68 | } 69 | } 70 | impl<'a> From<&'a str> for FfiError { 71 | fn from(error: &'a str) -> FfiError { 72 | FfiError::Unexpected(error.to_string()) 73 | } 74 | } 75 | 76 | impl From for FfiError { 77 | fn from(error: CoreError) -> FfiError { 78 | FfiError::CoreError(Box::new(error)) 79 | } 80 | } 81 | 82 | impl From for FfiError { 83 | fn from(error: NfsError) -> FfiError { 84 | FfiError::NfsError(Box::new(error)) 85 | } 86 | } 87 | 88 | impl From for FfiError { 89 | fn from(error: DnsError) -> FfiError { 90 | FfiError::DnsError(Box::new(error)) 91 | } 92 | } 93 | 94 | impl From for FfiError { 95 | fn from(_: base64::FromBase64Error) -> FfiError { 96 | FfiError::SpecificParseError("Base64 decode error".to_string()) 97 | } 98 | } 99 | 100 | impl From for FfiError { 101 | fn from(error: json::ParserError) -> FfiError { 102 | FfiError::JsonParseError(error) 103 | } 104 | } 105 | 106 | impl From for FfiError { 107 | fn from(error: json::EncoderError) -> FfiError { 108 | FfiError::JsonEncodeError(error) 109 | } 110 | } 111 | 112 | impl From for FfiError { 113 | fn from(error: json::DecoderError) -> FfiError { 114 | FfiError::JsonDecodeError(error) 115 | } 116 | } 117 | 118 | impl Into for FfiError { 119 | fn into(self) -> i32 { 120 | match self { 121 | FfiError::CoreError(error) => (*error).into(), 122 | FfiError::NfsError(error) => (*error).into(), 123 | FfiError::DnsError(error) => (*error).into(), 124 | FfiError::PathNotFound => FFI_ERROR_START_RANGE - 1, 125 | FfiError::InvalidPath => FFI_ERROR_START_RANGE - 2, 126 | FfiError::PermissionDenied => FFI_ERROR_START_RANGE - 3, 127 | FfiError::JsonParseError(_) => FFI_ERROR_START_RANGE - 4, 128 | FfiError::JsonDecodeError(_) => FFI_ERROR_START_RANGE - 5, 129 | FfiError::SpecificParseError(_) => FFI_ERROR_START_RANGE - 6, 130 | FfiError::JsonEncodeError(_) => FFI_ERROR_START_RANGE - 7, 131 | FfiError::LocalConfigAccessFailed(_) => FFI_ERROR_START_RANGE - 8, 132 | FfiError::Unexpected(_) => FFI_ERROR_START_RANGE - 9, 133 | FfiError::UnsuccessfulEncodeDecode(_) => FFI_ERROR_START_RANGE - 10, 134 | } 135 | } 136 | } 137 | 138 | impl fmt::Debug for FfiError { 139 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 140 | match *self { 141 | FfiError::CoreError(ref error) => write!(f, "FfiError::CoreError -> {:?}", error), 142 | FfiError::NfsError(ref error) => write!(f, "FfiError::NfsError -> {:?}", error), 143 | FfiError::DnsError(ref error) => write!(f, "FfiError::DnsError -> {:?}", error), 144 | FfiError::PathNotFound => write!(f, "FfiError::PathNotFound"), 145 | FfiError::InvalidPath => write!(f, "FfiError::InvalidPath"), 146 | FfiError::PermissionDenied => write!(f, "FfiError::PermissionDenied"), 147 | FfiError::JsonParseError(ref error) => { 148 | write!(f, "FfiError::JsonParseError -> {:?}", error) 149 | } 150 | FfiError::JsonDecodeError(ref error) => { 151 | write!(f, "FfiError::JsonDecodeError -> {:?}", error) 152 | } 153 | FfiError::SpecificParseError(ref error) => { 154 | write!(f, "FfiError::SpecificParseError -> {:?}", error) 155 | } 156 | FfiError::JsonEncodeError(ref error) => { 157 | write!(f, "FfiError::JsonEncodeError -> {:?}", error) 158 | } 159 | FfiError::LocalConfigAccessFailed(ref error) => { 160 | write!(f, "FfiError::LocalConfigAccessFailed -> {:?}", error) 161 | } 162 | FfiError::Unexpected(ref error) => write!(f, "FfiError::Unexpected{{{:?}}}", error), 163 | FfiError::UnsuccessfulEncodeDecode(ref err) => { 164 | write!(f, "FfiError::UnsuccessfulEncodeDecode -> {:?}", err) 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/helper.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use std::error::Error; 19 | use std::sync::{Arc, Mutex}; 20 | 21 | use libc::c_char; 22 | use std::ffi::CStr; 23 | use errors::FfiError; 24 | use safe_core::nfs::AccessLevel; 25 | use safe_core::core::client::Client; 26 | use config::SAFE_DRIVE_DIR_NAME; 27 | use safe_core::nfs::UNVERSIONED_DIRECTORY_LISTING_TAG; 28 | use safe_core::nfs::directory_listing::DirectoryListing; 29 | use safe_core::nfs::metadata::directory_key::DirectoryKey; 30 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 31 | 32 | #[allow(unsafe_code)] 33 | pub fn c_char_ptr_to_string(c_char_ptr: *const c_char) -> Result { 34 | let cstr = unsafe { CStr::from_ptr(c_char_ptr) }; 35 | Ok(try!(String::from_utf8(cstr.to_bytes().iter().map(|a| *a).collect()) 36 | .map_err(|error| FfiError::from(error.description())))) 37 | } 38 | 39 | pub fn tokenise_path(path: &str, keep_empty_splits: bool) -> Vec { 40 | path.split(|element| element == '/') 41 | .filter(|token| keep_empty_splits || token.len() != 0) 42 | .map(|token| token.to_string()) 43 | .collect() 44 | } 45 | 46 | pub fn get_safe_drive_key(client: Arc>) -> Result { 47 | let safe_drive_dir_name = SAFE_DRIVE_DIR_NAME.to_string(); 48 | let dir_helper = DirectoryHelper::new(client); 49 | let mut root_dir = try!(dir_helper.get_user_root_directory_listing()); 50 | let dir_metadata = match root_dir.find_sub_directory(&safe_drive_dir_name).map(|d| d.clone()) { 51 | Some(metadata) => metadata, 52 | None => { 53 | let (created_dir, _) = try!(dir_helper.create(safe_drive_dir_name, 54 | UNVERSIONED_DIRECTORY_LISTING_TAG, 55 | Vec::new(), 56 | false, 57 | AccessLevel::Private, 58 | Some(&mut root_dir))); 59 | created_dir.get_metadata().clone() 60 | } 61 | }; 62 | 63 | let key = dir_metadata.get_key().clone(); 64 | Ok(key) 65 | } 66 | 67 | pub fn get_final_subdirectory(client: Arc>, 68 | tokens: &Vec, 69 | starting_directory: Option<&DirectoryKey>) 70 | -> Result { 71 | let dir_helper = DirectoryHelper::new(client); 72 | 73 | let mut current_dir_listing = match starting_directory { 74 | Some(directory_key) => try!(dir_helper.get(directory_key)), 75 | None => try!(dir_helper.get_user_root_directory_listing()), 76 | }; 77 | 78 | for it in tokens.iter() { 79 | current_dir_listing = { 80 | let current_dir_metadata = try!(current_dir_listing.get_sub_directories() 81 | .iter() 82 | .find(|a| *a.get_name() == *it) 83 | .ok_or(FfiError::PathNotFound)); 84 | try!(dir_helper.get(current_dir_metadata.get_key())) 85 | }; 86 | } 87 | 88 | Ok(current_dir_listing) 89 | } 90 | -------------------------------------------------------------------------------- /src/launcher_config_handler.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use xor_name::XorName; 20 | use std::sync::{Arc, Mutex}; 21 | use safe_core::core::client::Client; 22 | use sodiumoxide::crypto::hash::sha512; 23 | use safe_core::nfs::helper::file_helper::FileHelper; 24 | use safe_core::nfs::helper::writer::Mode::Overwrite; 25 | use safe_core::nfs::directory_listing::DirectoryListing; 26 | use safe_core::nfs::metadata::directory_key::DirectoryKey; 27 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 28 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 29 | use maidsafe_utilities::serialisation::{serialise, deserialise}; 30 | use config::{LAUNCHER_GLOBAL_CONFIG_FILE_NAME, LAUNCHER_GLOBAL_DIRECTORY_NAME}; 31 | 32 | #[derive(RustcEncodable, RustcDecodable, Debug)] 33 | pub struct LauncherConfiguration { 34 | pub app_id: XorName, 35 | pub app_root_dir_key: DirectoryKey, 36 | } 37 | 38 | pub struct ConfigHandler { 39 | client: Arc>, 40 | } 41 | 42 | impl ConfigHandler { 43 | pub fn new(client: Arc>) -> ConfigHandler { 44 | ConfigHandler { client: client } 45 | } 46 | 47 | pub fn get_app_dir_key(&self, 48 | app_name: String, 49 | app_key: String, 50 | vendor: String) 51 | -> Result { 52 | let app_id = self.get_app_id(&app_key, &vendor); 53 | 54 | let (configs, _) = try!(self.get_launcher_global_config_and_dir()); 55 | let app_dir_key = match configs.iter() 56 | .find(|config| config.app_id == app_id) 57 | .map(|config| config.clone()) { 58 | Some(config) => config.app_root_dir_key.clone(), 59 | None => { 60 | let dir_helper = DirectoryHelper::new(self.client.clone()); 61 | let mut root_dir_listing = try!(dir_helper.get_user_root_directory_listing()); 62 | let app_dir_name = self.get_app_dir_name(&app_name, &root_dir_listing); 63 | let dir_key = try!(dir_helper.create(app_dir_name, 64 | UNVERSIONED_DIRECTORY_LISTING_TAG, 65 | Vec::new(), 66 | false, 67 | AccessLevel::Private, 68 | Some(&mut root_dir_listing))) 69 | .0 70 | .get_key() 71 | .clone(); 72 | let app_config = LauncherConfiguration { 73 | app_id: app_id, 74 | app_root_dir_key: dir_key.clone(), 75 | }; 76 | try!(self.upsert_to_launcher_global_config(app_config)); 77 | dir_key 78 | } 79 | }; 80 | 81 | Ok(app_dir_key) 82 | } 83 | 84 | fn get_app_id(&self, app_key: &String, vendor: &String) -> XorName { 85 | let mut id_str = String::new(); 86 | id_str.push_str(&app_key); 87 | id_str.push_str(&vendor); 88 | XorName::new(sha512::hash(id_str.as_bytes()).0) 89 | } 90 | 91 | fn get_app_dir_name(&self, app_name: &String, directory_listing: &DirectoryListing) -> String { 92 | let mut dir_name = format!("{}-Root-Dir", &app_name); 93 | if directory_listing.find_sub_directory(&dir_name).is_some() { 94 | let mut index = 1u8; 95 | loop { 96 | dir_name = format!("{}-{}-Root-Dir", &app_name, index); 97 | if directory_listing.find_sub_directory(&dir_name).is_some() { 98 | index += 1; 99 | } else { 100 | break; 101 | } 102 | } 103 | } 104 | 105 | dir_name 106 | } 107 | 108 | fn upsert_to_launcher_global_config(&self, 109 | config: LauncherConfiguration) 110 | -> Result<(), FfiError> { 111 | let (mut global_configs, dir_listing) = try!(self.get_launcher_global_config_and_dir()); 112 | 113 | // (Spandan) 114 | // Unable to use `if let Some() .. else` logic to upsert to a vector due to a language bug. 115 | // Once the bug is resolved 116 | // - https://github.com/rust-lang/rust/issues/28449 117 | // then modify the following to use it. 118 | if let Some(pos) = global_configs.iter().position(|existing_config| { 119 | existing_config.app_id == config.app_id 120 | }) { 121 | let existing_config = unwrap_option!(global_configs.get_mut(pos), 122 | "Logic Error - Report bug."); 123 | *existing_config = config; 124 | } else { 125 | global_configs.push(config); 126 | } 127 | 128 | let file = unwrap_option!(dir_listing.get_files() 129 | .iter() 130 | .find(|file| { 131 | file.get_name() == LAUNCHER_GLOBAL_CONFIG_FILE_NAME 132 | }), 133 | "Logic Error - Launcher start-up should ensure the file must \ 134 | be present at this stage - Report bug.") 135 | .clone(); 136 | 137 | let file_helper = FileHelper::new(self.client.clone()); 138 | let mut writer = try!(file_helper.update_content(file, Overwrite, dir_listing)); 139 | writer.write(&try!(serialise(&global_configs)), 0); 140 | let _ = try!(writer.close()); 141 | 142 | Ok(()) 143 | } 144 | 145 | fn get_launcher_global_config_and_dir 146 | (&self) 147 | -> Result<(Vec, DirectoryListing), FfiError> { 148 | let dir_helper = DirectoryHelper::new(self.client.clone()); 149 | let mut dir_listing = try!(dir_helper.get_configuration_directory_listing( 150 | LAUNCHER_GLOBAL_DIRECTORY_NAME.to_string())); 151 | 152 | let global_configs = { 153 | let file_helper = FileHelper::new(self.client.clone()); 154 | let file = match dir_listing.get_files() 155 | .iter() 156 | .find(|file| { 157 | file.get_name() == LAUNCHER_GLOBAL_CONFIG_FILE_NAME 158 | }) 159 | .map(|f| f.clone()) { 160 | Some(file) => file, 161 | None => { 162 | dir_listing = 163 | try!(try!(file_helper.create(LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string(), 164 | Vec::new(), 165 | dir_listing)) 166 | .close()) 167 | .0; 168 | unwrap_option!(dir_listing.get_files() 169 | .iter() 170 | .find(|file| { 171 | file.get_name() == 172 | LAUNCHER_GLOBAL_CONFIG_FILE_NAME 173 | }) 174 | .map(|f| f.clone()), 175 | "Error") 176 | .clone() 177 | } 178 | }; 179 | let mut reader = file_helper.read(&file); 180 | 181 | let size = reader.size(); 182 | 183 | if size != 0 { 184 | try!(deserialise(&try!(reader.read(0, size)))) 185 | } else { 186 | Vec::new() 187 | } 188 | }; 189 | 190 | Ok((global_configs, dir_listing)) 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | //! This crate provides FFI-bindings to the Client Modules (`safe_core`, `safe_nfs`, `safe_dns`) 19 | //! In the current implementation the allocations made by this crate are managed within the crate 20 | //! itself and is guaranteed that management of such allocations will not be pushed beyond the FFI 21 | //! boundary. This has a 2-fold outcome: firstly, the passing of data is done by filling of the 22 | //! allocations passed by the caller and is caller's responsibility to manage those. For this every 23 | //! function that fills an allocated memory also has a companion function to return the size of 24 | //! data which the caller can call to find out how much space needs to be allocated in the first 25 | //! place. Second and consequently, the caller does not have to bother calling functions within 26 | //! this crate which only serve to free resources allocated by the crate itself. This otherwise 27 | //! would be error prone and cumbersome. Instead the caller can use whatever idiom in his language 28 | //! to manage memory much more naturally and conveniently (eg., RAII idioms etc) 29 | //! 30 | //! The only exception to the above rule is the obtainment of the client engine itself. The client 31 | //! engine is allocated and managed by the crate. This is necessary because it serves as a context 32 | //! to all operations provided by the crate. Hence the user will obtain the engine on calling any 33 | //! one of the functions to create it and must preserve it for all subsequent operations. When 34 | //! done, to release the resources, `drop_client` may be called. 35 | //! 36 | //! [Project github page](https://github.com/maidsafe/safe_ffi) 37 | 38 | #![doc(html_logo_url = 39 | "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png", 40 | html_favicon_url = "http://maidsafe.net/img/favicon.ico", 41 | html_root_url = "http://maidsafe.github.io/safe_ffi")] 42 | 43 | // For explanation of lint checks, run `rustc -W help` or see 44 | // https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md 45 | 46 | #![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items, 47 | unknown_crate_types, warnings)] 48 | #![deny(deprecated, drop_with_repr_extern, improper_ctypes, missing_docs, 49 | non_shorthand_field_patterns, overflowing_literals, plugin_as_library, 50 | private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion, 51 | unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes, 52 | unused_comparisons, unused_features, unused_parens, while_true)] 53 | #![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, 54 | unused_qualifications, unused_results)] 55 | #![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations, 56 | missing_debug_implementations, variant_size_differences)] 57 | 58 | #![cfg_attr(feature="clippy", feature(plugin))] 59 | #![cfg_attr(feature="clippy", plugin(clippy))] 60 | #![cfg_attr(feature="clippy", deny(clippy, clippy_pedantic))] 61 | 62 | 63 | #[macro_use] 64 | extern crate log; 65 | extern crate libc; 66 | extern crate xor_name; 67 | extern crate safe_core; 68 | extern crate sodiumoxide; 69 | extern crate rustc_serialize; 70 | #[macro_use] 71 | extern crate maidsafe_utilities; 72 | 73 | use errors::FfiError; 74 | use rustc_serialize::json; 75 | use std::sync::{Arc, Mutex, mpsc}; 76 | use rustc_serialize::Decoder; 77 | use safe_core::core::client::Client; 78 | use rustc_serialize::Decodable; 79 | use libc::{c_void, int32_t, c_char}; 80 | use std::mem; 81 | use rustc_serialize::base64::FromBase64; 82 | use maidsafe_utilities::serialisation::{serialise, deserialise}; 83 | use maidsafe_utilities::thread::RaiiThreadJoiner; 84 | use maidsafe_utilities::log as safe_log; 85 | use safe_core::nfs::metadata::directory_key::DirectoryKey; 86 | use safe_core::core::translated_events::NetworkEvent; 87 | use safe_core::core::errors::CoreError; 88 | use std::sync::mpsc::Sender; 89 | 90 | #[macro_use]mod macros; 91 | 92 | mod dns; 93 | mod nfs; 94 | mod config; 95 | mod helper; 96 | mod test_utils; 97 | mod launcher_config_handler; 98 | /// Errors thrown by the FFI operations 99 | pub mod errors; 100 | 101 | 102 | /// ParameterPacket acts as a holder for the standard parameters that would be needed for performing 103 | /// operations across the modules like nfs and dns 104 | pub struct ParameterPacket { 105 | /// Client instance used for performing the API operation 106 | pub client: Arc>, 107 | /// Root directory of the application 108 | pub app_root_dir_key: Option, 109 | /// Denotes whether the application has access to SAFEDrive 110 | pub safe_drive_access: bool, 111 | /// SAFEDrive root directory key 112 | pub safe_drive_dir_key: Option, 113 | } 114 | 115 | impl Clone for ParameterPacket { 116 | fn clone(&self) -> ParameterPacket { 117 | let app_root_dir_key = if let Some(ref key) = self.app_root_dir_key { 118 | Some(key.clone()) 119 | } else { 120 | None 121 | }; 122 | let safe_drive_dir_key = if let Some(ref key) = self.safe_drive_dir_key { 123 | Some(key.clone()) 124 | } else { 125 | None 126 | }; 127 | ParameterPacket { 128 | client: self.client.clone(), 129 | app_root_dir_key: app_root_dir_key, 130 | safe_drive_access: self.safe_drive_access, 131 | safe_drive_dir_key: safe_drive_dir_key, 132 | } 133 | } 134 | } 135 | 136 | /// ResponseType tspecifies the standard Response that is to be expected from the ::Action trait 137 | pub type ResponseType = Result, ::errors::FfiError>; 138 | 139 | /// ICommand trait 140 | pub trait Action { 141 | /// ICommand executer 142 | fn execute(&mut self, params: ParameterPacket) -> ResponseType; 143 | } 144 | 145 | struct FfiHandle { 146 | client: Arc>, 147 | network_thread_terminator: Option>, 148 | raii_joiner: Option, 149 | network_event_observers: Arc>>, 150 | } 151 | 152 | impl Drop for FfiHandle { 153 | fn drop(&mut self) { 154 | if let Some(ref network_thread_terminator) = self.network_thread_terminator { 155 | let _ = network_thread_terminator.send(NetworkEvent::Terminated); 156 | } 157 | } 158 | } 159 | 160 | /// This function should be called to enable logging to a file 161 | #[no_mangle] 162 | pub extern "C" fn init_logging() -> int32_t { 163 | ffi_try!(safe_log::init(false).map_err(CoreError::Unexpected)); 164 | 165 | 0 166 | } 167 | 168 | /// Create an unregistered client. This or any one of the other companion functions to get a 169 | /// client must be called before initiating any operation allowed by this crate. 170 | #[no_mangle] 171 | #[allow(unsafe_code)] 172 | pub extern "C" fn create_unregistered_client(ffi_handle: *mut *const c_void) -> int32_t { 173 | unsafe { 174 | *ffi_handle = cast_to_ffi_handle(ffi_try!(Client::create_unregistered_client())); 175 | } 176 | 177 | 0 178 | } 179 | 180 | /// Create a registered client. This or any one of the other companion functions to get a 181 | /// client must be called before initiating any operation allowed by this crate. `client_handle` is 182 | /// a pointer to a pointer and must point to a valid pointer not junk, else the consequences are 183 | /// undefined. 184 | #[no_mangle] 185 | #[allow(unsafe_code)] 186 | pub extern "C" fn create_account(c_keyword: *const c_char, 187 | c_pin: *const c_char, 188 | c_password: *const c_char, 189 | ffi_handle: *mut *const c_void) 190 | -> int32_t { 191 | let client = ffi_try!(Client::create_account(ffi_try!(helper::c_char_ptr_to_string(c_keyword)), 192 | ffi_try!(helper::c_char_ptr_to_string(c_pin)), 193 | ffi_try!(helper::c_char_ptr_to_string(c_password)))); 194 | unsafe { 195 | *ffi_handle = cast_to_ffi_handle(client); 196 | } 197 | 198 | 0 199 | } 200 | 201 | /// Log into a registered client. This or any one of the other companion functions to get a 202 | /// client must be called before initiating any operation allowed by this crate. `client_handle` is 203 | /// a pointer to a pointer and must point to a valid pointer not junk, else the consequences are 204 | /// undefined. 205 | #[no_mangle] 206 | #[allow(unsafe_code)] 207 | pub extern "C" fn log_in(c_keyword: *const c_char, 208 | c_pin: *const c_char, 209 | c_password: *const c_char, 210 | ffi_handle: *mut *const c_void) 211 | -> int32_t { 212 | let client = ffi_try!(Client::log_in(ffi_try!(helper::c_char_ptr_to_string(c_keyword)), 213 | ffi_try!(helper::c_char_ptr_to_string(c_pin)), 214 | ffi_try!(helper::c_char_ptr_to_string(c_password)))); 215 | unsafe { 216 | *ffi_handle = cast_to_ffi_handle(client); 217 | } 218 | 219 | 0 220 | } 221 | 222 | /// Register an observer to network events like Connected, Disconnected etc. as provided by the 223 | /// core module 224 | #[no_mangle] 225 | #[allow(unsafe_code)] 226 | pub extern "C" fn register_network_event_observer(handle: *const c_void, 227 | callback: extern "C" fn(i32)) { 228 | let mut ffi_handle: Box = unsafe { mem::transmute(handle) }; 229 | 230 | unwrap_result!(ffi_handle.network_event_observers.lock()).push(callback); 231 | 232 | if ffi_handle.raii_joiner.is_none() { 233 | let callbacks = ffi_handle.network_event_observers.clone(); 234 | 235 | let (tx, rx) = mpsc::channel(); 236 | let cloned_tx = tx.clone(); 237 | unwrap_result!(ffi_handle.client.lock()).add_network_event_observer(tx); 238 | 239 | let raii_joiner = RaiiThreadJoiner::new(thread!("FfiNetworkEventObserver", move || { 240 | for it in rx.iter() { 241 | let ref cbs = *unwrap_result!(callbacks.lock()); 242 | let event_ffi_val = it.into(); 243 | for cb in cbs { 244 | cb(event_ffi_val); 245 | } 246 | } 247 | })); 248 | 249 | ffi_handle.raii_joiner = Some(raii_joiner); 250 | ffi_handle.network_thread_terminator = Some(cloned_tx); 251 | } 252 | 253 | mem::forget(ffi_handle); 254 | } 255 | 256 | /// Returns key size 257 | #[no_mangle] 258 | #[allow(unsafe_code)] 259 | pub extern "C" fn get_app_dir_key(c_app_name: *const c_char, 260 | c_app_id: *const c_char, 261 | c_vendor: *const c_char, 262 | c_size: *mut int32_t, 263 | c_capacity: *mut int32_t, 264 | c_result: *mut int32_t, 265 | ffi_handle: *const c_void) 266 | -> *const u8 { 267 | let client = cast_from_ffi_handle(ffi_handle); 268 | let app_name: String = ffi_ptr_try!(helper::c_char_ptr_to_string(c_app_name), c_result); 269 | let app_id: String = ffi_ptr_try!(helper::c_char_ptr_to_string(c_app_id), c_result); 270 | let vendor: String = ffi_ptr_try!(helper::c_char_ptr_to_string(c_vendor), c_result); 271 | let handler = launcher_config_handler::ConfigHandler::new(client); 272 | let dir_key = ffi_ptr_try!(handler.get_app_dir_key(app_name, app_id, vendor), c_result); 273 | let mut serialised_data = ffi_ptr_try!(serialise(&dir_key).map_err(|e| FfiError::from(e)), 274 | c_result); 275 | serialised_data.shrink_to_fit(); 276 | unsafe { 277 | std::ptr::write(c_size, serialised_data.len() as i32); 278 | std::ptr::write(c_capacity, serialised_data.capacity() as i32); 279 | std::ptr::write(c_result, 0); 280 | } 281 | 282 | let ptr = serialised_data.as_ptr(); 283 | mem::forget(serialised_data); 284 | 285 | ptr 286 | } 287 | 288 | /// Returns Key as base64 string 289 | #[no_mangle] 290 | #[allow(unsafe_code)] 291 | pub extern "C" fn get_safe_drive_key(c_size: *mut int32_t, 292 | c_capacity: *mut int32_t, 293 | c_result: *mut int32_t, 294 | ffi_handle: *const c_void) 295 | -> *const u8 { 296 | let client = cast_from_ffi_handle(ffi_handle); 297 | let dir_key = ffi_ptr_try!(helper::get_safe_drive_key(client), c_result); 298 | let mut serialised_data = ffi_ptr_try!(serialise(&dir_key).map_err(|e| FfiError::from(e)), 299 | c_result); 300 | serialised_data.shrink_to_fit(); 301 | unsafe { 302 | std::ptr::write(c_size, serialised_data.len() as i32); 303 | std::ptr::write(c_capacity, serialised_data.capacity() as i32); 304 | std::ptr::write(c_result, 0); 305 | } 306 | let ptr = serialised_data.as_ptr(); 307 | mem::forget(serialised_data); 308 | 309 | ptr 310 | } 311 | 312 | /// Discard and clean up the previously allocated client. Use this only if the client is obtained 313 | /// from one of the client obtainment functions in this crate (`crate_account`, `log_in`, 314 | /// `create_unregistered_client`). Using `client_handle` after a call to this functions is 315 | /// undefined behaviour. 316 | #[no_mangle] 317 | #[allow(unsafe_code)] 318 | pub extern "C" fn drop_client(client_handle: *const c_void) { 319 | let _ = unsafe { mem::transmute::<_, Box>>>(client_handle) }; 320 | } 321 | 322 | /// General function that can be invoked for performing a API specific operation that will return 323 | /// only result to indicate whether the operation was successful or not. 324 | /// This function would only perform the operation and return 0 or error code 325 | /// c_payload refers to the JSON payload that can be passed as a JSON string. 326 | /// The JSON string should have keys module, action, app_root_dir_key, safe_drive_dir_key, 327 | /// safe_drive_access and data. `data` refers to API specific payload. 328 | #[no_mangle] 329 | pub extern "C" fn execute(c_payload: *const c_char, ffi_handle: *const c_void) -> int32_t { 330 | let payload: String = ffi_try!(helper::c_char_ptr_to_string(c_payload)); 331 | let json_request = ffi_try!(parse_result!(json::Json::from_str(&payload), "JSON parse error")); 332 | let mut json_decoder = json::Decoder::new(json_request); 333 | let client = cast_from_ffi_handle(ffi_handle); 334 | let (module, action, parameter_packet) = ffi_try!(get_parameter_packet(client, 335 | &mut json_decoder)); 336 | let result = module_parser(module, action, parameter_packet, &mut json_decoder); 337 | let _ = ffi_try!(result); 338 | 339 | 0 340 | } 341 | 342 | /// General function that can be invoked for getting data as a resut for an operation. 343 | /// The function return a pointer to a U8 vecotr. The size of the U8 vector and its capacity is 344 | /// written to the out params c_size & c_capacity. The size and capcity would be required for 345 | /// droping the vector The result of the execution is returned in the c_result out param 346 | #[no_mangle] 347 | #[allow(unsafe_code)] 348 | pub extern "C" fn execute_for_content(c_payload: *const c_char, 349 | c_size: *mut int32_t, 350 | c_capacity: *mut int32_t, 351 | c_result: *mut int32_t, 352 | ffi_handle: *const c_void) 353 | -> *const u8 { 354 | let payload: String = ffi_ptr_try!(helper::c_char_ptr_to_string(c_payload), c_result); 355 | let json_request = ffi_ptr_try!(parse_result!(json::Json::from_str(&payload), 356 | "JSON parse error"), 357 | c_result); 358 | let mut json_decoder = json::Decoder::new(json_request.clone()); 359 | let client = cast_from_ffi_handle(ffi_handle); 360 | let (module, action, parameter_packet) = ffi_ptr_try!(get_parameter_packet(client, 361 | &mut json_decoder), 362 | c_result); 363 | // TODO Krishna: Avoid parsing it twice (line 292). for get_parameter_packet pass the json 364 | // object and iterate. parse based on keys 365 | json_decoder = json::Decoder::new(json_request.clone()); 366 | let result = ffi_ptr_try!(module_parser(module, action, parameter_packet, &mut json_decoder), 367 | c_result); 368 | let data = match result { 369 | Some(response) => response.into_bytes(), 370 | None => Vec::with_capacity(0), 371 | }; 372 | 373 | unsafe { 374 | std::ptr::write(c_size, data.len() as i32); 375 | std::ptr::write(c_capacity, data.capacity() as i32); 376 | std::ptr::write(c_result, 0); 377 | }; 378 | let ptr = data.as_ptr(); 379 | mem::forget(data); 380 | 381 | ptr 382 | } 383 | 384 | #[no_mangle] 385 | #[allow(unsafe_code)] 386 | /// Drop the vector returned as a result of the execute_for_content fn 387 | pub fn drop_vector(ptr: *mut u8, size: int32_t, capacity: int32_t) { 388 | let _ = unsafe { Vec::from_raw_parts(ptr, size as usize, capacity as usize) }; 389 | } 390 | 391 | #[no_mangle] 392 | #[allow(unsafe_code)] 393 | /// Drop the null pointer returned as error from the execute_for_content fn 394 | pub fn drop_null_ptr(ptr: *mut u8) { 395 | let _ = unsafe { libc::free(ptr as *mut c_void) }; 396 | } 397 | 398 | fn get_parameter_packet(client: Arc>, 399 | json_decoder: &mut D) 400 | -> Result<(String, String, ParameterPacket), ::errors::FfiError> 401 | where D: Decoder, 402 | D::Error: ::std::fmt::Debug 403 | { 404 | 405 | let module: String = try!(parse_result!(json_decoder.read_struct_field("module", 0, |d| { 406 | Decodable::decode(d) 407 | }), 408 | "")); 409 | let action: String = try!(parse_result!(json_decoder.read_struct_field("action", 1, |d| { 410 | Decodable::decode(d) 411 | }), 412 | "")); 413 | let base64_safe_drive_dir_key: Option = 414 | json_decoder.read_struct_field("safe_drive_dir_key", 2, |d| Decodable::decode(d)) 415 | .ok(); 416 | 417 | let base64_app_dir_key: Option = json_decoder.read_struct_field("app_dir_key", 418 | 3, 419 | |d| { 420 | Decodable::decode(d) 421 | }) 422 | .ok(); 423 | let safe_drive_access: bool = if base64_safe_drive_dir_key.is_none() { 424 | false 425 | } else { 426 | try!(parse_result!(json_decoder.read_struct_field("safe_drive_access", 427 | 4, 428 | |d| Decodable::decode(d)), 429 | "")) 430 | }; 431 | let app_root_dir_key: Option = if let Some(app_dir_key) = base64_app_dir_key { 432 | let serialised_app_dir_key: Vec = try!(parse_result!(app_dir_key[..].from_base64(), 433 | "")); 434 | let dir_key: DirectoryKey = try!(deserialise(&serialised_app_dir_key)); 435 | Some(dir_key) 436 | } else { 437 | None 438 | }; 439 | 440 | let safe_drive_dir_key: Option = if let Some(safe_dir_key) = 441 | base64_safe_drive_dir_key { 442 | let serialised_safe_drive_key: Vec = try!(parse_result!(safe_dir_key[..] 443 | .from_base64(), 444 | "")); 445 | let dir_key: DirectoryKey = try!(deserialise(&serialised_safe_drive_key)); 446 | Some(dir_key) 447 | } else { 448 | None 449 | }; 450 | 451 | Ok((module, 452 | action, 453 | ParameterPacket { 454 | client: client, 455 | app_root_dir_key: app_root_dir_key, 456 | safe_drive_access: safe_drive_access, 457 | safe_drive_dir_key: safe_drive_dir_key, 458 | })) 459 | } 460 | 461 | fn module_parser(module: String, 462 | action: String, 463 | parameter_packet: ParameterPacket, 464 | decoder: &mut D) 465 | -> ResponseType 466 | where D: Decoder, 467 | D::Error: ::std::fmt::Debug 468 | { 469 | match &module[..] { 470 | "dns" => dns::action_dispatcher(action, parameter_packet, decoder), 471 | "nfs" => nfs::action_dispatcher(action, parameter_packet, decoder), 472 | _ => unimplemented!(), 473 | } 474 | } 475 | 476 | #[allow(unsafe_code)] 477 | fn cast_to_ffi_handle(client: Client) -> *const c_void { 478 | let ffi_handle = Box::new(FfiHandle { 479 | client: Arc::new(Mutex::new(client)), 480 | network_thread_terminator: None, 481 | raii_joiner: None, 482 | network_event_observers: Arc::new(Mutex::new(Vec::with_capacity(3))), 483 | }); 484 | 485 | unsafe { mem::transmute(ffi_handle) } 486 | } 487 | 488 | #[allow(unsafe_code)] 489 | fn cast_from_ffi_handle(handle: *const c_void) -> Arc> { 490 | let ffi_handle: Box = unsafe { mem::transmute(handle) }; 491 | 492 | let client = ffi_handle.client.clone(); 493 | mem::forget(ffi_handle); 494 | 495 | client 496 | } 497 | 498 | #[cfg(test)] 499 | mod test { 500 | #![allow(unsafe_code)] 501 | 502 | use super::*; 503 | 504 | use std::env; 505 | use std::thread; 506 | use std::fs::File; 507 | use std::io::Read; 508 | use std::error::Error; 509 | use std::time::Duration; 510 | 511 | use libc::c_void; 512 | 513 | fn generate_random_cstring(len: usize) -> Result<::std::ffi::CString, ::errors::FfiError> { 514 | let mut cstring_vec = try!(::safe_core::core::utility::generate_random_vector::(len)); 515 | // Avoid internal nulls and ensure valid ASCII (thus valid utf8) 516 | for it in cstring_vec.iter_mut() { 517 | *it %= 128; 518 | if *it == 0 { 519 | *it += 1; 520 | } 521 | } 522 | 523 | ::std::ffi::CString::new(cstring_vec) 524 | .map_err(|error| ::errors::FfiError::from(error.description())) 525 | } 526 | 527 | #[test] 528 | fn account_creation_and_login() { 529 | let cstring_pin = unwrap_result!(generate_random_cstring(10)); 530 | let cstring_keyword = unwrap_result!(generate_random_cstring(10)); 531 | let cstring_password = unwrap_result!(generate_random_cstring(10)); 532 | 533 | { 534 | let mut client_handle = 0 as *const c_void; 535 | assert_eq!(client_handle, 0 as *const c_void); 536 | 537 | { 538 | let ptr_to_client_handle = &mut client_handle; 539 | 540 | let _ = assert_eq!(create_account(cstring_keyword.as_ptr(), 541 | cstring_pin.as_ptr(), 542 | cstring_password.as_ptr(), 543 | ptr_to_client_handle), 544 | 0); 545 | } 546 | 547 | assert!(client_handle != 0 as *const c_void); 548 | drop_client(client_handle); 549 | } 550 | 551 | { 552 | let mut client_handle = 0 as *const c_void; 553 | assert_eq!(client_handle, 0 as *const c_void); 554 | 555 | { 556 | let ptr_to_client_handle = &mut client_handle; 557 | 558 | let _ = assert_eq!(log_in(cstring_keyword.as_ptr(), 559 | cstring_pin.as_ptr(), 560 | cstring_password.as_ptr(), 561 | ptr_to_client_handle), 562 | 0); 563 | } 564 | 565 | assert!(client_handle != 0 as *const c_void); 566 | // let size_of_c_uint64 = ::std::mem::size_of::<::libc::int32_t>(); 567 | // let c_size = unsafe { ::libc::malloc(size_of_c_uint64) } as *mut ::libc::int32_t; 568 | // let c_capacity = unsafe { ::libc::malloc(size_of_c_uint64) } as *mut ::libc::int32_t; 569 | // let c_result = unsafe { ::libc::malloc(size_of_c_uint64) } as *mut ::libc::int32_t; 570 | // let ptr = get_safe_drive_key(c_size, c_capacity, c_result, client_handle); 571 | // unsafe { 572 | // let res = *c_result; 573 | // assert_eq!(res, 0); 574 | // let t = *ptr as *mut u8; 575 | // drop_vector(t, *c_size, *c_capacity); 576 | // } 577 | 578 | 579 | drop_client(client_handle); 580 | } 581 | } 582 | 583 | // Enable this test when doing explicit file-logging 584 | #[test] 585 | #[ignore] 586 | fn file_logging() { 587 | assert_eq!(init_logging(), 0); 588 | 589 | let debug_msg = "This is a sample debug message".to_owned(); 590 | let junk_msg = "This message should not exist in the log file".to_owned(); 591 | 592 | debug!("{}", debug_msg); 593 | 594 | thread::sleep(Duration::from_secs(1)); 595 | 596 | let mut current_exe_path = unwrap_result!(env::current_exe()); 597 | 598 | assert!(current_exe_path.set_extension("log")); 599 | 600 | // Give sometime to the async logging to flush in the background thread 601 | thread::sleep(Duration::from_millis(50)); 602 | 603 | let mut log_file = unwrap_result!(File::open(current_exe_path)); 604 | let mut file_content = String::new(); 605 | 606 | assert!(unwrap_result!(log_file.read_to_string(&mut file_content)) > 0); 607 | 608 | assert!(file_content.contains(&debug_msg[..])); 609 | assert!(!file_content.contains(&junk_msg[..])); 610 | } 611 | } 612 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | macro_rules! ffi_try { 19 | ($result:expr) => { 20 | match $result { 21 | Ok(value) => value, 22 | Err(error) => { 23 | let decorator = ::std::iter::repeat('-').take(50).collect::(); 24 | error!("\n\n {}\n| {:?}\n {}\n\n", decorator, error, decorator); 25 | return error.into() 26 | }, 27 | } 28 | } 29 | } 30 | 31 | macro_rules! ffi_ptr_try { 32 | ($result:expr, $out:expr) => { 33 | match $result { 34 | Ok(value) => value, 35 | Err(error) => { 36 | let decorator = ::std::iter::repeat('-').take(50).collect::(); 37 | error!("\n\n {}\n| {:?}\n {}\n\n", decorator, error, decorator); 38 | unsafe { ::std::ptr::write($out, error.into()) }; 39 | return ::std::ptr::null(); 40 | }, 41 | } 42 | } 43 | } 44 | 45 | 46 | /// This macro is intended to be used in all cases where we get an Err out of Result and want 47 | /// to package it into `safe_ffi::errors::FfiError::SpecificParseError(String)`. This is 48 | /// useful because there may be miscellaneous erros while parsing through a valid JSON due to JSON 49 | /// not conforming to certain mandatory requirements. This can then be communicated back to the 50 | /// JSON sending client. 51 | /// 52 | /// #Examples 53 | /// 54 | /// ``` 55 | /// # #[macro_use] extern crate safe_ffi; 56 | /// #[derive(Debug)] 57 | /// enum SomeSpecialError { 58 | /// Zero, 59 | /// One, 60 | /// } 61 | /// 62 | /// fn f() -> Result { 63 | /// Err(SomeSpecialError::One) 64 | /// } 65 | /// 66 | /// fn g() -> Result<(), safe_ffi::errors::FfiError> { 67 | /// let _module = try!(parse_result!(f(), "")); 68 | /// 69 | /// Ok(()) 70 | /// } 71 | /// 72 | /// fn main() { 73 | /// if let Err(err) = g() { 74 | /// println!("{:?}", err); 75 | /// } 76 | /// } 77 | /// ``` 78 | #[macro_export] 79 | macro_rules! parse_result { 80 | ($output:expr, $err_statement:expr) => { 81 | $output.map_err(|e| $crate::errors::FfiError::SpecificParseError( 82 | format!("{} {:?}", $err_statement.to_string(), e))) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/nfs/create_dir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG, 21 | VERSIONED_DIRECTORY_LISTING_TAG}; 22 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 23 | 24 | #[derive(RustcDecodable, Debug)] 25 | pub struct CreateDir { 26 | dir_path: String, 27 | is_private: bool, 28 | is_versioned: bool, 29 | user_metadata: String, 30 | is_path_shared: bool, 31 | } 32 | 33 | impl Action for CreateDir { 34 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 35 | use rustc_serialize::base64::FromBase64; 36 | 37 | if self.is_path_shared && !params.safe_drive_access { 38 | return Err(FfiError::PermissionDenied); 39 | } 40 | 41 | let mut tokens = helper::tokenise_path(&self.dir_path, false); 42 | let dir_to_create = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 43 | 44 | let start_dir_key = if self.is_path_shared { 45 | try!(params.safe_drive_dir_key 46 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 47 | } else { 48 | try!(params.app_root_dir_key 49 | .ok_or(FfiError::from("Application directory key is not present"))) 50 | }; 51 | 52 | let mut parent_sub_dir = try!(helper::get_final_subdirectory(params.client.clone(), 53 | &tokens, 54 | Some(&start_dir_key))); 55 | 56 | let dir_helper = DirectoryHelper::new(params.client); 57 | 58 | let access_level = if self.is_private { 59 | AccessLevel::Private 60 | } else { 61 | AccessLevel::Public 62 | }; 63 | 64 | let tag = if self.is_versioned { 65 | VERSIONED_DIRECTORY_LISTING_TAG 66 | } else { 67 | UNVERSIONED_DIRECTORY_LISTING_TAG 68 | }; 69 | 70 | let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), 71 | "Faild Converting from Base64.")); 72 | 73 | let _ = try!(dir_helper.create(dir_to_create, 74 | tag, 75 | bin_metadata, 76 | self.is_versioned, 77 | access_level, 78 | Some(&mut parent_sub_dir))); 79 | 80 | Ok(None) 81 | } 82 | } 83 | 84 | #[cfg(test)] 85 | mod test { 86 | use super::*; 87 | use {Action, test_utils}; 88 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 89 | 90 | #[test] 91 | fn create_dir() { 92 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 93 | 94 | let mut request = CreateDir { 95 | dir_path: "/".to_string(), 96 | is_private: true, 97 | is_versioned: false, 98 | user_metadata: "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), 99 | is_path_shared: false, 100 | }; 101 | assert!(request.execute(parameter_packet.clone()).is_err()); 102 | 103 | request.dir_path = "/test_dir/secondlevel".to_string(); 104 | assert!(request.execute(parameter_packet.clone()).is_err()); 105 | 106 | request.dir_path = "/test_dir".to_string(); 107 | assert!(request.execute(parameter_packet.clone()).is_ok()); 108 | 109 | request.dir_path = "/test_dir2".to_string(); 110 | assert!(request.execute(parameter_packet.clone()).is_ok()); 111 | 112 | request.dir_path = "/test_dir/secondlevel".to_string(); 113 | assert!(request.execute(parameter_packet.clone()).is_ok()); 114 | 115 | let dir_helper = DirectoryHelper::new(parameter_packet.clone().client); 116 | let app_dir = unwrap_result!(dir_helper.get(&unwrap_option!(parameter_packet.clone() 117 | .app_root_dir_key, 118 | ""))); 119 | assert!(app_dir.find_sub_directory(&"test_dir".to_string()).is_some()); 120 | assert!(app_dir.find_sub_directory(&"test_dir2".to_string()).is_some()); 121 | assert_eq!(app_dir.get_sub_directories().len(), 2); 122 | 123 | let test_dir_key = unwrap_option!(app_dir.find_sub_directory(&"test_dir".to_string()), 124 | "Directory not found") 125 | .get_key(); 126 | let test_dir = unwrap_result!(dir_helper.get(test_dir_key)); 127 | assert!(test_dir.find_sub_directory(&"secondlevel".to_string()).is_some()); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/nfs/create_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::file_helper::FileHelper; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct CreateFile { 24 | file_path: String, 25 | user_metadata: String, 26 | is_path_shared: bool, 27 | } 28 | 29 | impl Action for CreateFile { 30 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 31 | use rustc_serialize::base64::FromBase64; 32 | 33 | if self.is_path_shared && !params.safe_drive_access { 34 | return Err(FfiError::PermissionDenied); 35 | }; 36 | 37 | let start_dir_key = if self.is_path_shared { 38 | try!(params.safe_drive_dir_key 39 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 40 | } else { 41 | try!(params.app_root_dir_key 42 | .ok_or(FfiError::from("Application directory key is not present"))) 43 | }; 44 | 45 | let mut tokens = helper::tokenise_path(&self.file_path, false); 46 | let file_name = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 47 | 48 | let file_directory = try!(helper::get_final_subdirectory(params.client.clone(), 49 | &tokens, 50 | Some(&start_dir_key))); 51 | 52 | let file_helper = FileHelper::new(params.client); 53 | let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), 54 | "Failed Converting from Base64.")); 55 | 56 | let writer = try!(file_helper.create(file_name, bin_metadata, file_directory)); 57 | let _ = try!(writer.close()); 58 | 59 | Ok(None) 60 | } 61 | } 62 | 63 | #[cfg(test)] 64 | mod test { 65 | use super::*; 66 | use {Action, test_utils}; 67 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 68 | 69 | #[test] 70 | fn create_file() { 71 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 72 | 73 | let mut request = CreateFile { 74 | file_path: "/test.txt".to_string(), 75 | user_metadata: "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), 76 | is_path_shared: false, 77 | }; 78 | assert!(request.execute(parameter_packet.clone()).is_ok()); 79 | 80 | let dir_helper = DirectoryHelper::new(parameter_packet.client); 81 | let app_dir = 82 | unwrap_result!(dir_helper.get(&unwrap_option!(parameter_packet.app_root_dir_key, ""))); 83 | assert!(app_dir.find_file(&"test.txt".to_string()).is_some()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/nfs/delete_dir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct DeleteDir { 24 | dir_path: String, 25 | is_path_shared: bool, 26 | } 27 | 28 | impl Action for DeleteDir { 29 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 30 | let mut tokens = helper::tokenise_path(&self.dir_path, false); 31 | let dir_helper = DirectoryHelper::new(params.client.clone()); 32 | let dir_to_delete = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 33 | let root_dir = if self.is_path_shared { 34 | try!(dir_helper.get(&try!(params.safe_drive_dir_key 35 | .ok_or(FfiError::from("Safe Drive directory key \ 36 | is not present"))))) 37 | } else { 38 | try!(dir_helper.get(&try!(params.app_root_dir_key 39 | .ok_or(FfiError::from("Application directory key \ 40 | is not present"))))) 41 | }; 42 | 43 | let mut parent_dir = if tokens.len() == 0 { 44 | root_dir 45 | } else { 46 | try!(helper::get_final_subdirectory(params.client, 47 | &tokens, 48 | Some(root_dir.get_metadata() 49 | .get_key()))) 50 | }; 51 | let _ = try!(dir_helper.delete(&mut parent_dir, &dir_to_delete)); 52 | 53 | Ok(None) 54 | } 55 | } 56 | 57 | #[cfg(test)] 58 | mod test { 59 | use super::*; 60 | use {Action, test_utils}; 61 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 62 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 63 | 64 | #[test] 65 | fn delete_dir() { 66 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 67 | 68 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 69 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 70 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 71 | let _ = unwrap_result!(dir_helper.create("test_dir".to_string(), 72 | UNVERSIONED_DIRECTORY_LISTING_TAG, 73 | Vec::new(), 74 | false, 75 | AccessLevel::Private, 76 | Some(&mut app_root_dir))); 77 | 78 | 79 | let mut request = DeleteDir { 80 | dir_path: "/test_dir2".to_string(), 81 | is_path_shared: false, 82 | }; 83 | assert!(request.execute(parameter_packet.clone()).is_err()); 84 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 85 | assert_eq!(app_root_dir.get_sub_directories().len(), 1); 86 | assert!(app_root_dir.find_sub_directory(&"test_dir".to_string()).is_some()); 87 | request.dir_path = "/test_dir".to_string(); 88 | assert!(request.execute(parameter_packet.clone()).is_ok()); 89 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 90 | assert_eq!(app_root_dir.get_sub_directories().len(), 0); 91 | assert!(request.execute(parameter_packet.clone()).is_err()); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/nfs/delete_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::file_helper::FileHelper; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct DeleteFile { 24 | file_path: String, 25 | is_path_shared: bool, 26 | } 27 | 28 | impl Action for DeleteFile { 29 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 30 | let start_dir_key = if self.is_path_shared { 31 | try!(params.safe_drive_dir_key 32 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 33 | } else { 34 | try!(params.app_root_dir_key 35 | .ok_or(FfiError::from("Application directory key is not present"))) 36 | }; 37 | 38 | let mut tokens = helper::tokenise_path(&self.file_path, false); 39 | let file_name = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 40 | let mut dir_of_file = try!(helper::get_final_subdirectory(params.client.clone(), 41 | &tokens, 42 | Some(&start_dir_key))); 43 | 44 | let file_helper = FileHelper::new(params.client); 45 | let _ = try!(file_helper.delete(file_name, &mut dir_of_file)); 46 | 47 | Ok(None) 48 | } 49 | } 50 | 51 | 52 | #[cfg(test)] 53 | mod test { 54 | use super::*; 55 | use {Action, test_utils}; 56 | use safe_core::nfs::helper::file_helper::FileHelper; 57 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 58 | 59 | #[test] 60 | fn delete_file() { 61 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 62 | 63 | let file_helper = FileHelper::new(parameter_packet.client.clone()); 64 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 65 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 66 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 67 | let writer = unwrap_result!(file_helper.create("test_file.txt".to_string(), 68 | Vec::new(), 69 | app_root_dir)); 70 | let _ = unwrap_result!(writer.close()); 71 | 72 | let mut request = DeleteFile { 73 | file_path: "/test_file.txt".to_string(), 74 | is_path_shared: false, 75 | }; 76 | 77 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 78 | assert_eq!(app_root_dir.get_files().len(), 1); 79 | assert!(app_root_dir.find_file(&"test_file.txt".to_string()).is_some()); 80 | assert!(request.execute(parameter_packet.clone()).is_ok()); 81 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 82 | assert_eq!(app_root_dir.get_files().len(), 0); 83 | assert!(request.execute(parameter_packet.clone()).is_err()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/nfs/directory_response.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use std::sync::{Arc, Mutex}; 20 | use safe_core::core::client::Client; 21 | use safe_core::nfs::directory_listing::DirectoryListing; 22 | use safe_core::nfs::metadata::file_metadata::FileMetadata; 23 | use safe_core::nfs::metadata::directory_key::DirectoryKey; 24 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 25 | use safe_core::nfs::metadata::directory_metadata::DirectoryMetadata; 26 | 27 | #[derive(RustcEncodable, Debug)] 28 | pub struct GetDirResponse { 29 | info: DirectoryInfo, 30 | files: Vec, 31 | sub_directories: Vec, 32 | } 33 | 34 | #[derive(RustcEncodable, Debug)] 35 | struct DirectoryInfo { 36 | name: String, 37 | is_private: bool, 38 | is_versioned: bool, 39 | user_metadata: String, 40 | creation_time_sec: i64, 41 | creation_time_nsec: i64, 42 | modification_time_sec: i64, 43 | modification_time_nsec: i64, 44 | } 45 | 46 | #[derive(RustcEncodable, Debug)] 47 | struct FileInfo { 48 | name: String, 49 | size: i64, 50 | user_metadata: String, 51 | creation_time_sec: i64, 52 | creation_time_nsec: i64, 53 | modification_time_sec: i64, 54 | modification_time_nsec: i64, 55 | } 56 | 57 | pub fn get_response(client: Arc>, 58 | directory_key: DirectoryKey) 59 | -> Result { 60 | let dir_helper = DirectoryHelper::new(client); 61 | let dir_listing = try!(dir_helper.get(&directory_key)); 62 | Ok(convert_to_response(dir_listing)) 63 | } 64 | 65 | pub fn convert_to_response(directory_listing: DirectoryListing) -> GetDirResponse { 66 | let dir_info = get_directory_info(directory_listing.get_metadata()); 67 | let mut sub_dirs: Vec = 68 | Vec::with_capacity(directory_listing.get_sub_directories().len()); 69 | for metadata in directory_listing.get_sub_directories() { 70 | sub_dirs.push(get_directory_info(metadata)); 71 | } 72 | 73 | let mut files: Vec = Vec::with_capacity(directory_listing.get_files().len()); 74 | for file in directory_listing.get_files() { 75 | files.push(get_file_info(file.get_metadata())); 76 | } 77 | 78 | GetDirResponse { 79 | info: dir_info, 80 | files: files, 81 | sub_directories: sub_dirs, 82 | } 83 | } 84 | 85 | fn get_directory_info(dir_metadata: &DirectoryMetadata) -> DirectoryInfo { 86 | use rustc_serialize::base64::ToBase64; 87 | 88 | let dir_key = dir_metadata.get_key(); 89 | let created_time = dir_metadata.get_created_time().to_timespec(); 90 | let modified_time = dir_metadata.get_modified_time().to_timespec(); 91 | 92 | DirectoryInfo { 93 | name: dir_metadata.get_name().clone(), 94 | is_private: *dir_key.get_access_level() == ::safe_core::nfs::AccessLevel::Private, 95 | is_versioned: dir_key.is_versioned(), 96 | user_metadata: (*dir_metadata.get_user_metadata()) 97 | .to_base64(::config::get_base64_config()), 98 | creation_time_sec: created_time.sec, 99 | creation_time_nsec: created_time.nsec as i64, 100 | modification_time_sec: modified_time.sec, 101 | modification_time_nsec: modified_time.nsec as i64, 102 | } 103 | } 104 | 105 | fn get_file_info(file_metadata: &FileMetadata) -> FileInfo { 106 | use rustc_serialize::base64::ToBase64; 107 | 108 | let created_time = file_metadata.get_created_time().to_timespec(); 109 | let modified_time = file_metadata.get_modified_time().to_timespec(); 110 | FileInfo { 111 | name: file_metadata.get_name().clone(), 112 | size: file_metadata.get_size() as i64, 113 | user_metadata: (*file_metadata.get_user_metadata()) 114 | .to_base64(::config::get_base64_config()), 115 | creation_time_sec: created_time.sec, 116 | creation_time_nsec: created_time.nsec as i64, 117 | modification_time_sec: modified_time.sec, 118 | modification_time_nsec: modified_time.nsec as i64, 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/nfs/file_response.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use rustc_serialize::json; 19 | use std::collections::BTreeMap; 20 | use rustc_serialize::base64::ToBase64; 21 | 22 | use errors::FfiError; 23 | use safe_core::nfs::file::File; 24 | use std::sync::{Arc, Mutex}; 25 | use safe_core::core::client::Client; 26 | use safe_core::nfs::helper::file_helper::FileHelper; 27 | use safe_core::nfs::metadata::file_metadata::FileMetadata; 28 | 29 | #[derive(RustcEncodable, Debug)] 30 | pub struct GetFileResponse { 31 | content: String, 32 | metadata: Option, 33 | } 34 | 35 | #[derive(RustcEncodable, Debug)] 36 | struct Metadata { 37 | name: String, 38 | size: i64, 39 | user_metadata: String, 40 | creation_time_sec: i64, 41 | creation_time_nsec: i64, 42 | modification_time_sec: i64, 43 | modification_time_nsec: i64, 44 | } 45 | 46 | pub fn get_response(file: &File, 47 | client: Arc>, 48 | offset: i64, 49 | length: i64, 50 | include_metadata: bool) 51 | -> Result { 52 | let file_metadata = if include_metadata { 53 | Some(get_file_metadata(file.get_metadata())) 54 | } else { 55 | None 56 | }; 57 | let start_position = offset as u64; 58 | let file_helper = FileHelper::new(client); 59 | let mut reader = file_helper.read(&file); 60 | let mut size = length as u64; 61 | if size == 0 { 62 | size = reader.size() - start_position; 63 | }; 64 | Ok(GetFileResponse { 65 | content: try!(reader.read(start_position, size)).to_base64(::config::get_base64_config()), 66 | metadata: file_metadata, 67 | }) 68 | } 69 | 70 | fn get_file_metadata(file_metadata: &FileMetadata) -> Metadata { 71 | use rustc_serialize::base64::ToBase64; 72 | 73 | let created_time = file_metadata.get_created_time().to_timespec(); 74 | let modified_time = file_metadata.get_modified_time().to_timespec(); 75 | Metadata { 76 | name: file_metadata.get_name().clone(), 77 | size: file_metadata.get_size() as i64, 78 | user_metadata: (*file_metadata.get_user_metadata()) 79 | .to_base64(::config::get_base64_config()), 80 | creation_time_sec: created_time.sec, 81 | creation_time_nsec: created_time.nsec as i64, 82 | modification_time_sec: modified_time.sec, 83 | modification_time_nsec: modified_time.nsec as i64, 84 | } 85 | } 86 | 87 | impl json::ToJson for GetFileResponse { 88 | fn to_json(&self) -> json::Json { 89 | let mut response_tree = BTreeMap::new(); 90 | let _ = response_tree.insert("content".to_string(), self.content.to_json()); 91 | if let Some(ref metadata) = self.metadata { 92 | let json_metadata_str = unwrap_result!(json::encode(metadata)); 93 | let _ = response_tree.insert("metadata".to_string(), json_metadata_str.to_json()); 94 | } 95 | 96 | json::Json::Object(response_tree) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/nfs/get_dir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use nfs::directory_response::convert_to_response; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct GetDir { 24 | dir_path: String, 25 | is_path_shared: bool, 26 | } 27 | 28 | impl Action for GetDir { 29 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 30 | if self.is_path_shared && !params.safe_drive_access { 31 | return Err(FfiError::PermissionDenied); 32 | } 33 | 34 | let start_dir_key = if self.is_path_shared { 35 | try!(params.safe_drive_dir_key 36 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 37 | } else { 38 | try!(params.app_root_dir_key 39 | .ok_or(FfiError::from("Application directory key is not present"))) 40 | }; 41 | 42 | let tokens = helper::tokenise_path(&self.dir_path, false); 43 | let dir_fetched = try!(helper::get_final_subdirectory(params.client.clone(), 44 | &tokens, 45 | Some(&start_dir_key))); 46 | 47 | let response = convert_to_response(dir_fetched); 48 | 49 | Ok(Some(try!(::rustc_serialize::json::encode(&response)))) 50 | } 51 | } 52 | 53 | #[cfg(test)] 54 | mod test { 55 | use {Action, ParameterPacket, test_utils}; 56 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 57 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 58 | 59 | const TEST_DIR_NAME: &'static str = "test_dir"; 60 | 61 | fn create_test_dir(parameter_packet: &ParameterPacket) { 62 | let app_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 63 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 64 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_dir_key)); 65 | let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), 66 | UNVERSIONED_DIRECTORY_LISTING_TAG, 67 | Vec::new(), 68 | false, 69 | AccessLevel::Private, 70 | Some(&mut app_root_dir))); 71 | } 72 | 73 | #[test] 74 | fn get_dir() { 75 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 76 | 77 | create_test_dir(¶meter_packet); 78 | 79 | let mut request = super::GetDir { 80 | dir_path: format!("/{}", TEST_DIR_NAME), 81 | is_path_shared: false, 82 | }; 83 | 84 | assert!(unwrap_result!(request.execute(parameter_packet.clone())).is_some()); 85 | 86 | request.dir_path = "/does_not_exixts".to_string(); 87 | assert!(request.execute(parameter_packet).is_err()); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/nfs/get_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use rustc_serialize::json; 20 | use nfs::file_response::get_response; 21 | use {helper, ParameterPacket, ResponseType, Action}; 22 | 23 | #[derive(RustcDecodable, Debug)] 24 | pub struct GetFile { 25 | offset: i64, 26 | length: i64, 27 | file_path: String, 28 | is_path_shared: bool, 29 | include_metadata: bool, 30 | } 31 | 32 | impl Action for GetFile { 33 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 34 | use rustc_serialize::json::ToJson; 35 | 36 | if self.is_path_shared && !params.safe_drive_access { 37 | return Err(FfiError::PermissionDenied); 38 | } 39 | 40 | let mut tokens = helper::tokenise_path(&self.file_path, false); 41 | let file_name = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 42 | 43 | let start_dir_key = if self.is_path_shared { 44 | try!(params.safe_drive_dir_key 45 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 46 | } else { 47 | try!(params.app_root_dir_key 48 | .ok_or(FfiError::from("Application directory key is not present"))) 49 | }; 50 | 51 | let file_dir = try!(helper::get_final_subdirectory(params.client.clone(), 52 | &tokens, 53 | Some(&start_dir_key))); 54 | let file = try!(file_dir.find_file(&file_name) 55 | .ok_or(::errors::FfiError::InvalidPath)); 56 | 57 | let response = try!(get_response(file, 58 | params.client, 59 | self.offset, 60 | self.length, 61 | self.include_metadata)); 62 | 63 | Ok(Some(try!(json::encode(&response.to_json())))) 64 | } 65 | } 66 | 67 | 68 | #[cfg(test)] 69 | mod test { 70 | use {Action, ParameterPacket, test_utils}; 71 | use safe_core::nfs::helper::file_helper::FileHelper; 72 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 73 | 74 | const TEST_FILE_NAME: &'static str = "test_file.txt"; 75 | 76 | fn create_test_file(parameter_packet: &ParameterPacket) { 77 | let app_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 78 | let file_helper = FileHelper::new(parameter_packet.client.clone()); 79 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 80 | let app_root_dir = unwrap_result!(dir_helper.get(&app_dir_key)); 81 | let mut writer = unwrap_result!(file_helper.create(TEST_FILE_NAME.to_string(), 82 | Vec::new(), 83 | app_root_dir)); 84 | let data = vec![10u8; 20]; 85 | writer.write(&data[..], 0); 86 | let _ = unwrap_result!(writer.close()); 87 | } 88 | 89 | 90 | #[test] 91 | fn get_file() { 92 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 93 | 94 | create_test_file(¶meter_packet); 95 | 96 | let mut request = super::GetFile { 97 | offset: 0, 98 | length: 0, 99 | file_path: format!("/{}", TEST_FILE_NAME), 100 | is_path_shared: false, 101 | include_metadata: true, 102 | }; 103 | 104 | assert!(unwrap_result!(request.execute(parameter_packet.clone())).is_some()); 105 | 106 | request.file_path = "/does_not_exixts".to_string(); 107 | assert!(request.execute(parameter_packet).is_err()); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/nfs/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | use std::fmt; 18 | 19 | use rustc_serialize::Decoder; 20 | use rustc_serialize::Decodable; 21 | use errors::FfiError; 22 | 23 | mod create_dir; 24 | mod create_file; 25 | mod delete_dir; 26 | mod delete_file; 27 | mod get_dir; 28 | mod get_file; 29 | mod move_dir; 30 | mod move_file; 31 | mod modify_dir; 32 | mod modify_file; 33 | pub mod directory_response; 34 | pub mod file_response; 35 | 36 | pub fn action_dispatcher(action: String, 37 | params: ::ParameterPacket, 38 | decoder: &mut D) 39 | -> ::ResponseType 40 | where D: Decoder, 41 | D::Error: fmt::Debug 42 | { 43 | let mut action = try!(get_action(action, decoder)); 44 | action.execute(params) 45 | } 46 | 47 | fn get_action(action: String, decoder: &mut D) -> Result, FfiError> 48 | where D: Decoder, 49 | D::Error: fmt::Debug 50 | { 51 | Ok(match &action[..] { 52 | "create-dir" => { 53 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 54 | create_dir::CreateDir::decode(d) 55 | }), 56 | ""))) 57 | } 58 | "create-file" => { 59 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 60 | create_file::CreateFile::decode(d) 61 | }), 62 | ""))) 63 | } 64 | "delete-dir" => { 65 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 66 | delete_dir::DeleteDir::decode(d) 67 | }), 68 | ""))) 69 | } 70 | "delete-file" => { 71 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 72 | delete_file::DeleteFile::decode(d) 73 | }), 74 | ""))) 75 | } 76 | "get-dir" => { 77 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 78 | 0, 79 | |d| get_dir::GetDir::decode(d)), 80 | ""))) 81 | } 82 | "get-file" => { 83 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 84 | get_file::GetFile::decode(d) 85 | }), 86 | ""))) 87 | } 88 | "modify-dir" => { 89 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 90 | modify_dir::ModifyDir::decode(d) 91 | }), 92 | ""))) 93 | } 94 | "modify-file" => { 95 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 96 | modify_file::ModifyFile::decode(d) 97 | }), 98 | ""))) 99 | } 100 | "move-dir" => { 101 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 102 | move_dir::MoveDirectory::decode(d) 103 | }), 104 | ""))) 105 | } 106 | "move-file" => { 107 | Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { 108 | move_file::MoveFile::decode(d) 109 | }), 110 | ""))) 111 | } 112 | 113 | _ => { 114 | return Err(FfiError::SpecificParseError(format!("Unsupported action {:?} for this \ 115 | endpoint.", 116 | action))) 117 | } 118 | }) 119 | } 120 | -------------------------------------------------------------------------------- /src/nfs/modify_dir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 21 | 22 | #[derive(RustcDecodable, Debug)] 23 | pub struct ModifyDir { 24 | dir_path: String, 25 | new_values: OptionalParams, 26 | is_path_shared: bool, 27 | } 28 | 29 | impl Action for ModifyDir { 30 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 31 | use rustc_serialize::base64::FromBase64; 32 | 33 | if !(self.new_values.name.is_some() || self.new_values.user_metadata.is_some()) { 34 | return Err(FfiError::from("Optional parameters could not be parsed")); 35 | } 36 | 37 | if self.is_path_shared && !params.safe_drive_access { 38 | return Err(FfiError::PermissionDenied); 39 | } 40 | 41 | let start_dir_key = if self.is_path_shared { 42 | try!(params.safe_drive_dir_key 43 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 44 | } else { 45 | try!(params.app_root_dir_key 46 | .ok_or(FfiError::from("Application directory key is not present"))) 47 | }; 48 | 49 | let tokens = helper::tokenise_path(&self.dir_path, false); 50 | let mut dir_to_modify = try!(helper::get_final_subdirectory(params.client.clone(), 51 | &tokens, 52 | Some(&start_dir_key))); 53 | 54 | let directory_helper = DirectoryHelper::new(params.client); 55 | if let Some(ref name) = self.new_values.name { 56 | dir_to_modify.get_mut_metadata().set_name(name.clone()); 57 | } 58 | 59 | if let Some(ref metadata_base64) = self.new_values.user_metadata { 60 | let metadata = try!(parse_result!(metadata_base64.from_base64(), 61 | "Failed to convert from base64")); 62 | dir_to_modify.get_mut_metadata().set_user_metadata(metadata); 63 | } 64 | 65 | let _ = try!(directory_helper.update(&dir_to_modify)); 66 | 67 | Ok(None) 68 | } 69 | } 70 | 71 | #[derive(Debug, RustcDecodable)] 72 | struct OptionalParams { 73 | pub name: Option, 74 | pub user_metadata: Option, 75 | } 76 | 77 | #[cfg(test)] 78 | mod test { 79 | use super::*; 80 | use {Action, ParameterPacket, test_utils}; 81 | use rustc_serialize::base64::ToBase64; 82 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 83 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 84 | 85 | const TEST_DIR_NAME: &'static str = "test_dir"; 86 | const METADATA_BASE64: &'static str = "c2FtcGxlIHRleHQ="; 87 | 88 | fn create_test_dir(parameter_packet: &ParameterPacket) { 89 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 90 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 91 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 92 | let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), 93 | UNVERSIONED_DIRECTORY_LISTING_TAG, 94 | Vec::new(), 95 | false, 96 | AccessLevel::Private, 97 | Some(&mut app_root_dir))); 98 | } 99 | 100 | #[test] 101 | fn rename_dir() { 102 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 103 | 104 | create_test_dir(¶meter_packet); 105 | 106 | let values = super::OptionalParams { 107 | name: Some("new_test_dir".to_string()), 108 | user_metadata: None, 109 | }; 110 | 111 | let mut request = ModifyDir { 112 | dir_path: format!("/{}", TEST_DIR_NAME), 113 | new_values: values, 114 | is_path_shared: false, 115 | }; 116 | 117 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 118 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 119 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 120 | assert_eq!(app_root_dir.get_sub_directories().len(), 1); 121 | assert!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()).is_some()); 122 | assert!(request.execute(parameter_packet).is_ok()); 123 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 124 | assert_eq!(app_root_dir.get_sub_directories().len(), 1); 125 | assert!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()).is_none()); 126 | assert!(app_root_dir.find_sub_directory(&"new_test_dir".to_string()).is_some()); 127 | } 128 | 129 | #[test] 130 | fn dir_update_user_metadata() { 131 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 132 | 133 | create_test_dir(¶meter_packet); 134 | 135 | let values = super::OptionalParams { 136 | name: None, 137 | user_metadata: Some(METADATA_BASE64.to_string()), 138 | }; 139 | 140 | let mut request = ModifyDir { 141 | dir_path: format!("/{}", TEST_DIR_NAME), 142 | new_values: values, 143 | is_path_shared: false, 144 | }; 145 | 146 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 147 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 148 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 149 | let directory_key = 150 | unwrap_option!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()), 151 | "Directory not found") 152 | .get_key(); 153 | let mut directory_to_modify = unwrap_result!(dir_helper.get(directory_key)); 154 | assert_eq!(directory_to_modify.get_metadata().get_user_metadata().len(), 155 | 0); 156 | assert!(request.execute(parameter_packet).is_ok()); 157 | directory_to_modify = unwrap_result!(dir_helper.get(directory_key)); 158 | assert!(directory_to_modify.get_metadata().get_user_metadata().len() > 0); 159 | assert_eq!(directory_to_modify.get_metadata() 160 | .get_user_metadata() 161 | .to_base64(::config::get_base64_config()), 162 | METADATA_BASE64.to_string()); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/nfs/modify_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::file_helper::FileHelper; 21 | use safe_core::nfs::helper::writer::Mode; 22 | 23 | #[derive(RustcDecodable, Debug)] 24 | pub struct ModifyFile { 25 | file_path: String, 26 | new_values: OptionalParams, 27 | is_path_shared: bool, 28 | } 29 | 30 | impl Action for ModifyFile { 31 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 32 | use rustc_serialize::base64::FromBase64; 33 | 34 | if self.is_path_shared && !params.safe_drive_access { 35 | return Err(FfiError::PermissionDenied); 36 | } 37 | 38 | if self.new_values.name.is_none() && self.new_values.user_metadata.is_none() && 39 | self.new_values.content.is_none() { 40 | return Err(FfiError::from("Optional parameters could not be parsed")); 41 | } 42 | 43 | let start_dir_key = if self.is_path_shared { 44 | try!(params.safe_drive_dir_key 45 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 46 | } else { 47 | try!(params.app_root_dir_key 48 | .ok_or(FfiError::from("Application directory key is not present"))) 49 | }; 50 | let mut tokens = helper::tokenise_path(&self.file_path, false); 51 | let file_name = try!(tokens.pop().ok_or(FfiError::InvalidPath)); 52 | let mut dir_of_file = try!(helper::get_final_subdirectory(params.client.clone(), 53 | &tokens, 54 | Some(&start_dir_key))); 55 | 56 | let mut file = try!(dir_of_file.find_file(&file_name) 57 | .map(|file| file.clone()) 58 | .ok_or(FfiError::InvalidPath)); 59 | 60 | let file_helper = FileHelper::new(params.client); 61 | 62 | let mut metadata_updated = false; 63 | if let Some(ref name) = self.new_values.name { 64 | file.get_mut_metadata().set_name(name.clone()); 65 | metadata_updated = true; 66 | } 67 | 68 | if let Some(ref metadata_base64) = self.new_values.user_metadata { 69 | let metadata = try!(parse_result!(metadata_base64.from_base64(), 70 | "Failed to convert from base64")); 71 | file.get_mut_metadata().set_user_metadata(metadata); 72 | metadata_updated = true; 73 | } 74 | 75 | if metadata_updated { 76 | let _ = try!(file_helper.update_metadata(file.clone(), &mut dir_of_file)); 77 | } 78 | 79 | if let Some(ref file_content_params) = self.new_values.content { 80 | let (mode, offset) = match file_content_params.offset { 81 | Some(offset) => (Mode::Modify, offset), 82 | None => (Mode::Overwrite, 0), 83 | }; 84 | let mut writer = try!(file_helper.update_content(file.clone(), mode, dir_of_file)); 85 | let bytes = try!(parse_result!(file_content_params.bytes.from_base64(), 86 | "Failed to convert from base64")); 87 | writer.write(&bytes[..], offset); 88 | let _ = try!(writer.close()); 89 | } 90 | 91 | Ok(None) 92 | } 93 | } 94 | 95 | #[derive(RustcDecodable, Debug)] 96 | struct OptionalParams { 97 | pub name: Option, 98 | pub content: Option, 99 | pub user_metadata: Option, 100 | } 101 | 102 | #[derive(RustcDecodable, Debug)] 103 | struct FileContentParams { 104 | pub bytes: String, 105 | pub offset: Option, 106 | } 107 | 108 | #[cfg(test)] 109 | mod test { 110 | use super::{ModifyFile, FileContentParams, OptionalParams}; 111 | use {Action, ParameterPacket, test_utils}; 112 | use rustc_serialize::base64::ToBase64; 113 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 114 | use safe_core::nfs::helper::file_helper::FileHelper; 115 | 116 | const TEST_FILE_NAME: &'static str = "test_file.txt"; 117 | const METADATA_BASE64: &'static str = "c2FtcGxlIHRleHQ="; 118 | 119 | fn create_test_file(parameter_packet: &ParameterPacket) { 120 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 121 | let file_helper = FileHelper::new(parameter_packet.client.clone()); 122 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 123 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 124 | let writer = unwrap_result!(file_helper.create(TEST_FILE_NAME.to_string(), 125 | Vec::new(), 126 | app_root_dir)); 127 | let _ = unwrap_result!(writer.close()); 128 | } 129 | 130 | #[test] 131 | fn file_rename() { 132 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 133 | 134 | create_test_file(¶meter_packet); 135 | 136 | let values = OptionalParams { 137 | name: Some("new_test_file.txt".to_string()), 138 | content: None, 139 | user_metadata: None, 140 | }; 141 | 142 | let mut request = ModifyFile { 143 | file_path: format!("/{}", TEST_FILE_NAME), 144 | new_values: values, 145 | is_path_shared: false, 146 | }; 147 | 148 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 149 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 150 | let mut app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 151 | assert_eq!(app_root_dir.get_files().len(), 1); 152 | assert!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()).is_some()); 153 | 154 | assert!(request.execute(parameter_packet).is_ok()); 155 | app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 156 | assert_eq!(app_root_dir.get_files().len(), 1); 157 | assert!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()).is_none()); 158 | assert!(app_root_dir.find_file(&"new_test_file.txt".to_string()).is_some()); 159 | } 160 | 161 | #[test] 162 | fn file_update_user_metadata() { 163 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 164 | 165 | create_test_file(¶meter_packet); 166 | 167 | let values = OptionalParams { 168 | name: None, 169 | content: None, 170 | user_metadata: Some(METADATA_BASE64.to_string()), 171 | }; 172 | 173 | let mut request = ModifyFile { 174 | file_path: format!("/{}", TEST_FILE_NAME), 175 | new_values: values, 176 | is_path_shared: false, 177 | }; 178 | 179 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 180 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 181 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 182 | let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), 183 | "File not found"); 184 | assert_eq!(file.get_metadata().get_user_metadata().len(), 0); 185 | assert!(request.execute(parameter_packet).is_ok()); 186 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 187 | let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), 188 | "File not found"); 189 | assert!(file.get_metadata().get_user_metadata().len() > 0); 190 | assert_eq!(file.get_metadata() 191 | .get_user_metadata() 192 | .to_base64(::config::get_base64_config()), 193 | METADATA_BASE64.to_string()); 194 | } 195 | 196 | #[test] 197 | fn file_update_content() { 198 | let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); 199 | 200 | create_test_file(¶meter_packet); 201 | 202 | let content = FileContentParams { 203 | bytes: METADATA_BASE64.to_string(), 204 | offset: None, 205 | }; 206 | 207 | let values = OptionalParams { 208 | name: None, 209 | content: Some(content), 210 | user_metadata: None, 211 | }; 212 | 213 | let mut request = ModifyFile { 214 | file_path: format!("/{}", TEST_FILE_NAME), 215 | new_values: values, 216 | is_path_shared: false, 217 | }; 218 | 219 | let app_root_dir_key = unwrap_option!(parameter_packet.clone().app_root_dir_key, ""); 220 | let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); 221 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 222 | let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), 223 | "File not found"); 224 | assert_eq!(file.get_metadata().get_size(), 0); 225 | assert!(request.execute(parameter_packet.clone()).is_ok()); 226 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 227 | let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), 228 | "File not found"); 229 | let file_size = file.get_metadata().get_size(); 230 | assert!(file_size > 0); 231 | let file_helper = FileHelper::new(parameter_packet.client.clone()); 232 | let mut reader = file_helper.read(file); 233 | let size = reader.size(); 234 | assert_eq!(size, file_size); 235 | let data = unwrap_result!(reader.read(0, size)); 236 | assert_eq!(data.to_base64(::config::get_base64_config()), 237 | METADATA_BASE64.to_string()); 238 | // Uploading in smaller chunks 239 | let file_size = 8011; 240 | let batch_size = 1000; 241 | let mut i = 0; 242 | 243 | while i < file_size { 244 | let content = FileContentParams { 245 | bytes: METADATA_BASE64.to_string(), 246 | offset: Some(i), // offset: Some(i * batch_size), 247 | }; 248 | 249 | let values = OptionalParams { 250 | name: None, 251 | content: Some(content), 252 | user_metadata: None, 253 | }; 254 | 255 | request = ModifyFile { 256 | file_path: format!("/{}", TEST_FILE_NAME), 257 | new_values: values, 258 | is_path_shared: false, 259 | }; 260 | assert!(request.execute(parameter_packet.clone()).is_ok()); 261 | i += batch_size; 262 | } 263 | 264 | let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); 265 | let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()) 266 | .map(|a| a.clone()), 267 | "File not found"); 268 | assert_eq!(file.get_datamap().len(), file_size); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /src/nfs/move_dir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 21 | use safe_core::nfs::directory_listing::DirectoryListing; 22 | use safe_core::nfs::errors::NfsError::DirectoryAlreadyExistsWithSameName; 23 | 24 | #[derive(RustcDecodable, Debug)] 25 | pub struct MoveDirectory { 26 | src_path: String, 27 | is_src_path_shared: bool, 28 | dest_path: String, 29 | is_dest_path_shared: bool, 30 | retain_source: bool, 31 | } 32 | 33 | impl MoveDirectory { 34 | fn get_directory(&self, 35 | params: &ParameterPacket, 36 | shared: bool, 37 | path: &String) 38 | -> Result { 39 | let start_dir_key = if shared { 40 | try!(params.clone() 41 | .safe_drive_dir_key 42 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 43 | } else { 44 | try!(params.clone() 45 | .app_root_dir_key 46 | .ok_or(FfiError::from("Application directory key is not present"))) 47 | }; 48 | 49 | let tokens = helper::tokenise_path(path, false); 50 | helper::get_final_subdirectory(params.client.clone(), &tokens, Some(&start_dir_key)) 51 | } 52 | } 53 | 54 | impl Action for MoveDirectory { 55 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 56 | if (self.is_src_path_shared || self.is_dest_path_shared) && !params.safe_drive_access { 57 | return Err(FfiError::PermissionDenied); 58 | } 59 | let directory_helper = DirectoryHelper::new(params.client.clone()); 60 | let mut src_dir = try!(self.get_directory(¶ms, 61 | self.is_src_path_shared, 62 | &self.src_path)); 63 | let mut dest_dir = try!(self.get_directory(¶ms, 64 | self.is_dest_path_shared, 65 | &self.dest_path)); 66 | if dest_dir.find_sub_directory(src_dir.get_metadata().get_name()).is_some() { 67 | return Err(FfiError::from(DirectoryAlreadyExistsWithSameName)); 68 | } 69 | let org_parent_of_src_dir = src_dir.get_metadata().get_key().clone(); 70 | if self.retain_source { 71 | let name = src_dir.get_metadata().get_name().clone(); 72 | let user_metadata = src_dir.get_metadata().get_user_metadata().clone(); 73 | let access_level = src_dir.get_metadata().get_access_level().clone(); 74 | let created_time = src_dir.get_metadata().get_created_time().clone(); 75 | let modified_time = src_dir.get_metadata().get_modified_time().clone(); 76 | let mut dir = try!(DirectoryListing::new(name, 77 | src_dir.get_metadata() 78 | .get_key() 79 | .get_type_tag(), 80 | user_metadata, 81 | src_dir.get_metadata() 82 | .get_key() 83 | .is_versioned(), 84 | access_level, 85 | src_dir.get_metadata() 86 | .get_parent_dir_key() 87 | .map(|key| key.clone()))); 88 | src_dir.get_files().iter().all(|file| { 89 | dir.get_mut_files().push(file.clone()); 90 | true 91 | }); 92 | src_dir.get_sub_directories() 93 | .iter() 94 | .all(|sub_dir| { 95 | dir.get_mut_sub_directories().push(sub_dir.clone()); 96 | true 97 | }); 98 | dir.get_mut_metadata().set_created_time(created_time); 99 | dir.get_mut_metadata().set_modified_time(modified_time); 100 | src_dir = dir; 101 | } else { 102 | src_dir.get_mut_metadata() 103 | .set_parent_dir_key(Some(dest_dir.get_metadata().get_key().clone())); 104 | } 105 | dest_dir.upsert_sub_directory(src_dir.get_metadata().clone()); 106 | let _ = try!(directory_helper.update(&dest_dir)); 107 | let _ = try!(directory_helper.update(&src_dir)); 108 | if !self.retain_source { 109 | let mut parent_of_src_dir = try!(directory_helper.get(&org_parent_of_src_dir)); 110 | try!(parent_of_src_dir.remove_sub_directory(dest_dir.get_metadata() 111 | .get_name())); 112 | let _ = try!(directory_helper.update(&parent_of_src_dir)); 113 | } 114 | Ok(None) 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/nfs/move_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use errors::FfiError; 19 | use {helper, ParameterPacket, ResponseType, Action}; 20 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 21 | use safe_core::nfs::directory_listing::DirectoryListing; 22 | use safe_core::nfs::errors::NfsError::DirectoryAlreadyExistsWithSameName; 23 | 24 | #[derive(RustcDecodable, Debug)] 25 | pub struct MoveFile { 26 | src_path: String, 27 | is_src_path_shared: bool, 28 | dest_path: String, 29 | is_dest_path_shared: bool, 30 | retain_source: bool, 31 | } 32 | 33 | impl MoveFile { 34 | fn get_directory_and_file(&self, 35 | params: &ParameterPacket, 36 | shared: bool, 37 | path: &String) 38 | -> Result<(DirectoryListing, String), FfiError> { 39 | let start_dir_key = if shared { 40 | try!(params.clone() 41 | .safe_drive_dir_key 42 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 43 | } else { 44 | try!(params.clone() 45 | .app_root_dir_key 46 | .ok_or(FfiError::from("Application directory key is not present"))) 47 | }; 48 | 49 | let mut tokens = helper::tokenise_path(path, false); 50 | let file_name = try!(tokens.pop().ok_or(FfiError::PathNotFound)); 51 | let directory_listing = try!(helper::get_final_subdirectory(params.client.clone(), 52 | &tokens, 53 | Some(&start_dir_key))); 54 | Ok((directory_listing, file_name)) 55 | } 56 | 57 | fn get_directory(&self, 58 | params: &ParameterPacket, 59 | shared: bool, 60 | path: &String) 61 | -> Result { 62 | let start_dir_key = if shared { 63 | try!(params.clone() 64 | .safe_drive_dir_key 65 | .ok_or(FfiError::from("Safe Drive directory key is not present"))) 66 | } else { 67 | try!(params.clone() 68 | .app_root_dir_key 69 | .ok_or(FfiError::from("Application directory key is not present"))) 70 | }; 71 | 72 | let tokens = helper::tokenise_path(path, false); 73 | helper::get_final_subdirectory(params.client.clone(), &tokens, Some(&start_dir_key)) 74 | } 75 | } 76 | 77 | impl Action for MoveFile { 78 | fn execute(&mut self, params: ParameterPacket) -> ResponseType { 79 | if (self.is_src_path_shared || self.is_dest_path_shared) && !params.safe_drive_access { 80 | return Err(FfiError::PermissionDenied); 81 | } 82 | let directory_helper = DirectoryHelper::new(params.client.clone()); 83 | let (mut src_dir, src_file_name) = try!(self.get_directory_and_file(¶ms, 84 | self.is_src_path_shared, 85 | &self.src_path)); 86 | let mut dest_dir = try!(self.get_directory(¶ms, 87 | self.is_dest_path_shared, 88 | &self.dest_path)); 89 | if dest_dir.find_file(&src_file_name).is_some() { 90 | return Err(FfiError::from(DirectoryAlreadyExistsWithSameName)); 91 | } 92 | let file = match src_dir.find_file(&src_file_name).map(|file| file.clone()) { 93 | Some(file) => file, 94 | None => return Err(FfiError::PathNotFound), 95 | }; 96 | dest_dir.upsert_file(file); 97 | let _ = try!(directory_helper.update(&dest_dir)); 98 | if !self.retain_source { 99 | try!(src_dir.remove_file(&src_file_name)); 100 | let _ = try!(directory_helper.update(&src_dir)); 101 | } 102 | Ok(None) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/test_utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, 4 | // version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which 5 | // licence you accepted on initial access to the Software (the "Licences"). 6 | // 7 | // By contributing code to the SAFE Network Software, or to this project generally, you agree to be 8 | // bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the 9 | // Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. 10 | // 11 | // Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed 12 | // under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. 14 | // 15 | // Please review the Licences for the specific language governing permissions and limitations 16 | // relating to use of the SAFE Network Software. 17 | 18 | use std::sync::{Arc, Mutex}; 19 | 20 | use errors::FfiError; 21 | use ParameterPacket; 22 | use safe_core::core::utility::test_utils; 23 | use safe_core::nfs::helper::directory_helper::DirectoryHelper; 24 | use safe_core::nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; 25 | 26 | #[allow(unused)] 27 | pub fn get_parameter_packet(has_safe_drive_access: bool) -> Result { 28 | let client = Arc::new(Mutex::new(try!(test_utils::get_client()))); 29 | let directory_helper = DirectoryHelper::new(client.clone()); 30 | let mut user_root_dir = try!(directory_helper.get_user_root_directory_listing()); 31 | let (safe_drive, _) = try!(directory_helper.create(::config::SAFE_DRIVE_DIR_NAME.to_string(), 32 | UNVERSIONED_DIRECTORY_LISTING_TAG, 33 | Vec::new(), 34 | false, 35 | AccessLevel::Private, 36 | Some(&mut user_root_dir))); 37 | let (test_app, _) = try!(directory_helper.create("Test_Application".to_string(), 38 | UNVERSIONED_DIRECTORY_LISTING_TAG, 39 | Vec::new(), 40 | false, 41 | AccessLevel::Private, 42 | Some(&mut user_root_dir))); 43 | Ok(ParameterPacket { 44 | client: client, 45 | app_root_dir_key: Some(test_app.get_key().clone()), 46 | safe_drive_access: has_safe_drive_access, 47 | safe_drive_dir_key: Some(safe_drive.get_key().clone()), 48 | }) 49 | } 50 | 51 | 52 | #[allow(unused)] 53 | pub fn get_unregistered_parameter_packet() -> Result { 54 | let client = 55 | Arc::new(Mutex::new(try!(::safe_core::core::client::Client::create_unregistered_client()))); 56 | Ok(ParameterPacket { 57 | client: client, 58 | app_root_dir_key: None, 59 | safe_drive_access: false, 60 | safe_drive_dir_key: None, 61 | }) 62 | } 63 | --------------------------------------------------------------------------------